как декодировать несколько / одно значение в Json

#json #go

# #json #Вперед

Вопрос:

Я хочу декодировать запрос JSON, чтобы значением поля могла быть одна строка или массив (список).

Я знаю, как анализировать if отдельно. но я ищу способ иметь динамический декодер для анализа их обоих.

value Поле в JSON — это тот случай, о котором я говорю

Пример для однозначного:

 {
    "filter":{
        "op":"IN",
        "field":"name",
        "value": "testDuplicate"
    }
}
 

Пример для многозначного:

 {
    "filter":{
        "op":"IN",
        "field":"name",
        "value":["testDuplicate","tt"]
    }
}
 

Структуры для одного значения:

 type DocumentTypeSearchRequest struct {
    Filter   DocTypeFilter `json:"filter"`
}
type DocTypeFilter struct {
    Op    string `json:"op"`
    Field string `json:"field"`
    Value string `json:"value"`
}
 

Структуры для многозначных:

 type DocumentTypeSearchRequest struct {
    Filter   DocTypeFilter `json:"filter"`
}
type DocTypeFilter struct {
    Op    string `json:"op"`
    Field string `json:"field"`
    Value []string `json:"value"`
}  
 

Одно из решений — попытаться декодировать с помощью одного из них, если не удалось использовать другой, но я не уверен, что это правильный способ решения этой проблемы.

Комментарии:

1. @Jamiec один из них — строка Value [], а другой — json:"value" строка Value json:"value" имеет ли это смысл?

2. @super пожалуйста, взгляните на мой комментарий. из них это фрагмент строки, а другой — просто строка

3. Нет, потому что ваш ввод json всегда содержит массив значений в json (должно ли одно из них иметь только одно значение? если нет, что вы собираетесь делать с остальными?)

4. @ value Jamiec здесь дело в поле. это какой-то запрос, это всего лишь строка. в некоторых запросах это список строк.

Ответ №1:

Вам нужен пользовательский разделитель. Я говорил о подобной ситуации в этом видео:

 type Value []string

func (v *Value) UnmarshalJSON(p []byte) error {
    if p[0] == '[' { // First char is '[', so it's a JSON array
        s := make([]string, 0)
        err := json.Unmarshal(p, amp;s)
        *v = Value(s)
        return err
    }
    // else it's a simple string
    *v = make(Value, 1)
    return json.Unmarshal(p, amp;(*v)[0])
}
 

Ссылка на игровую площадку

С этим определением Value ваша структура станет чем-то вроде:

 type DocTypeFilter struct {
    Op    string `json:"op"`
    Field string `json:"field"`
    Value Value  `json:"value"`
}
 

и теперь ваше Value поле всегда будет срезом, но оно может содержать только одно значение, когда ваш ввод JSON представляет собой строку, а не массив.

Комментарии:

1.Я не уверен, что это работает так, как вы думали (или, скорее всего, будучи новичком в Go, я не могу настроить ваше решение, которое я просто использую в качестве учебного материала!) cannot unmarshal string into Go struct field DocTypeFilter.filter.value of type []main.Value ссылка на игровую площадку

2. Не используйте []Value , используйте Value . Value сам по себе теперь является срезом, как []Value и срез срезов (не то, что вы хотите).

3. @Flimzy спасибо за решение. Я попробовал это с моим случаем `{«filter»:{«op»:»EQ»,»field»:»name»,»value»:»testDuplicate»}, «page»:0,»page_size»:0} json, но он возвращает ошибку. не могли бы вы, пожалуйста, обновить игровую площадку с образцом тоже? большое спасибо.

4. Вы имеете в виду вот так? play.golang.org/p/H_CcSaG-rmz

5. @Flimzy я имел в виду решение, которое анализирует образец json в вопросе. это «{«filter»:{«op»:»EQ»,»field»:»name»,»value»:»testDuplicate»},»page»:0,»page_size»: 0}». полный json