2015-05-27 7 views
0

Учитывая следующий вход:Go - Изменить JSON на лету

"object": { 
    "array": [ 
    { 
     "element_field_1": some_value_1, 
     "element_field_2": some_value_1, 
     ... // More unknown fields 
    }, 
    ... 
    ], 
    "object_field": foo, 
    ... // Some more unknown fields 
} 

мне нужно перебирать каждый элемент массива, изменять поля 1 и 2, а затем выводит объект JSON. Вот что у меня есть сейчас, но она далека от действительного кода Go:

func handler(w http.ResponseWriter, r *http.Request) { 
    // Transform the request's body to an interface 
    j := getDecodedJSON(r) 

    // Iterate over every element of the array 
    for i := 0; i < len(j["object"]["array"]); i++ { 
     rewrite(j["object"]["array"][i]) 
    } 

    // Encoding back to JSON shouldn't be a problem 
} 

func getDecodedJSON(r *http.Request) map[string]interface{} { 
    dec := json.NewDecoder(r.Body) 
    var j map[string]interface{} 
    if err := dec.Decode(&j); err != nil { 
     log.Fatal(err) 
    } 
    return j 
} 

func rewrite(element *map[string]interface{}) { 
    element["element_field_1"], element["element_field_2"] = lookupValues(element) 
} 

В основном ошибка:

invalid operation: j["object"]["array"] \ 
(type interface {} does not support indexing) 

, но, конечно, есть более концептуальная ошибка в моем подходе.

Запись struct, которая детализирует содержимое ввода, на самом деле не является вариантом, так как я заранее не знаю ключей JSON.

Как я могу это сделать «Путь»?

EDIT: Это фактическое использование случай:

  • У меня есть два веб-службы, которые нуждаются в «переводчика» между ними.
  • Служба 1 делает запрос к переводчику, где изменяется несколько полей, все остальное остается нетронутым.
  • Затем переводчик принимает измененный JSON и повторяет запрос на обслуживание 2.

Другими словами, этот переводчик действует как человек в середине для обеих служб. Похоже, что это хороший вариант для этого, учитывая его быстрое время запуска и быструю обработку JSON.

Я не думаю, что имеет смысл подробно описывать каждое поле JSON в структуре Go, так как мне нужно только изменить несколько полей. Я готов сделать компромисс по эффективности из-за отражения (синтаксический анализ на map[string]interface{} должен быть медленнее, чем использование полномасштабной структуры), в обмен на то, чтобы сделать код более общим для вариаций входа JSON.

+0

Вы знаете типы неизвестных полей? – inf

+0

@ дюймовый нет, не очень. Но если у вас есть обходное решение, связанное с пониманием типов, то, я думаю, я мог бы что-то сделать – jlhonora

ответ

0

Изменить

j["object"]["array"][i] 

в

j["object"].(map[string]interface{})["array"].([]interface{})[i]