Подтвердить что ты не робот

Gson - имя одного и того же поля, разные типы

Я задал это по другому вопросу сегодня, но я боюсь, что это не получит решения из-за того, как оно было сформулировано.

У меня есть вход json, который имеет следующие данные:

Json

Как вы можете видеть, элемент option_value - это массив в одном объекте и простая строка в другом объекте.

Как я могу заставить Gson справиться с этим правильно? В моем классе это описано как объект List, поэтому он работает для первых нескольких элементов, где option_value является массивом, но когда он становится строкой, приложение падает, и я получаю синтаксический анализ json исключение.

Есть ли обходной путь для этого?

UPDATE

Добавление соответствующей части моего класса в соответствии с запросом:

public class Options
    {
        String product_option_id;
        String option_id;
        String name;
        String type;
        String required;
        List<OptionValue> option_value;

        // get set stuff here

        public class OptionValue
        {
            String product_option_value_id;
            String option_value_id;
            String name;
            String image;
            String price;
            String price_prefix;

            // get set stuff here
        }
    }
4b9b3361

Ответ 1

У меня есть решение для вас:) Для этого мы должны использовать пользовательский десериализатор. Переделайте свой класс следующим образом:

public class Options{

    @SerializedName ("product_option_id");
    String mProductOptionId;

    @SerializedName ("option_id");
    String mOptionId;

    @SerializedName ("name");
    String mName;

    @SerializedName ("type");
    String mType;

    @SerializedName ("required");
    String mRequired;

    //don't assign any serialized name, this field will be parsed manually
    List<OptionValue> mOptionValue;

    //setter
    public void setOptionValues(List<OptionValue> optionValues){
         mOptionValue = optionValues;
    }

    // get set stuff here
    public class OptionValue
    {
        String product_option_value_id;
        String option_value_id;
        String name;
        String image;
        String price;
        String price_prefix;

        // get set stuff here
    }

public static class OptionsDeserilizer implements JsonDeserializer<Options> {

    @Override
    public Offer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        Options options = new Gson().fromJson(json, Options.class);
        JsonObject jsonObject = json.getAsJsonObject();

        if (jsonObject.has("option_value")) {
            JsonElement elem = jsonObject.get("option_value");
            if (elem != null && !elem.isJsonNull()) {  
                 String valuesString = elem.getAsString();
                 if (!TextUtils.isEmpty(valuesString)){
                     List<OptionValue> values = new Gson().fromJson(valuesString, new TypeToken<ArrayList<OptionValue>>() {}.getType());
                     options.setOptionValues(values);
                 }
            }
        }
        return options ;
    }
}
}

Прежде чем мы сможем разрешить gson parse json, мы должны зарегистрировать наш пользовательский десериализатор:

Gson gson = new GsonBuilder()              
            .registerTypeAdapter(Options.class, new Options.OptionsDeserilizer())               
            .create();

А теперь - просто позвоните:

Options options = gson.fromJson(json, Options.class);

Ответ 2

В моей ситуации поле с таким же именем - это "данные": {} или "data": [array_with_real_data]. Поэтому код из принятого ответа нужно немного изменить, например:

@Override
public MyClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {
    MyClass bean = new Gson().fromJson(json, MyClass.class);
    JsonObject jsonObject = json.getAsJsonObject();

    if (jsonObject.has("data")) {
        JsonArray array = jsonObject.getAsJsonArray("data");
        if (array != null && !array.isJsonNull()) {
            List<Data> data = new Gson().fromJson(array, new TypeToken<ArrayList<Data>>() {}.getType());
            bean.realData = data;
        }
    }
    return bean ;
}

надеюсь, что это поможет.