Java JSON在类型为String或List <string>

时间:2016-12-09 06:32:14

标签: java json serialization

是否有一种简单的方法可以反序列化可能是StringList<String>的值?

我必须处理一个我将缩写为的大型JSON:

{"A": {"item1": 1,
        ...
       "itemN": "SomeString",
        ...
       "itemM": 123.45},
 "B": { ... },
 "C": { ... },
 }

有时它看起来像这样:

{"A": {"item1": 1,
        ...
       "itemN": ["SomeString1", "SomeString2"],
        ...
       "itemM": 123.45},
 "B": { ... },
 "C": { ... },
 }

我反序列化:

MyData data = new Gson().fromJson(rxJSON, DataClass.class);

DataClass:

@Parcel
public class DataClass {
    @SerializedName("A")
    private AClass groupA;
    @SerializedName("B")
    private BClass groupB;
    @SerializedName("C")
    private BClass groupC;
    ... getters/setters ...
}

和AClass:

@Parcel
public class AClass {
    @SerializedName("item1")
    private int item1;
    ...
    @SerializedName("itemN")
    private List<String> itemN;
    ...
    @SerializedName("itemM")
    private float itemM;
    ... getters/setters ...
}

理想情况下,我想将AClass用于两个JSON,而在itemNString的情况下,只需将其视为单个元素{{ 1}}(即将List<String>视为"SomeString")。反序列化后,我总是希望在其余代码中将其作为简单列表访问。

我已经看到了对Polymophism解决方案和解决方案的建议,建议尝试使用一个类的一个版本(假设["SomeString"])进行反序列化,并在异常中使用类的一个版本反序列化反序列化类型(例如String)。其他解决方案建议更多手动/分段反序列化,它一次只反序列化JSON层次结构的一个级别,直到我来List<String>然后检查它的类型。似乎应该有一个更简单的方法。有吗?

1 个答案:

答案 0 :(得分:1)

我找到了一个很好的解决方案,谢谢: https://stackoverflow.com/a/31563539/3571110https://stackoverflow.com/a/6205384/3571110

第一个链接显示为整个JSON使用自定义反序列化器(对我来说太多工作),并在其中管理StringList<String>。第二个链接让我了解了我可以为List<>等基本类型创建自定义反序列化器(我以前认为我只能使用自定义类)。结合这些想法并做出适当的改变(其他一切都保持不变):

解决方案:

public class ListOrStringDeserializer implements JsonDeserializer<List<String>> {

    @Override
    public List<String> deserialize(JsonElement json, Type typeOfT,
                                    JsonDeserializationContext context) 
            throws JsonParseException {

        List<String> items = Collections.emptyList();
        if (json.isJsonArray()) {
            items = context.deserialize(json, List.class);
        } else if (json.isJsonPrimitive()) {
            items = Collections.singletonList((String) context.deserialize(json, String.class));
        }
        return items;
    }
}

然后在反序列化之前注册:

Gson gson = new GsonBuilder().registerTypeAdapter(new TypeToken<List<String>>() {}.getType(), new ListOrStringDeserializer()).create();
MyData data = gson.fromJson(rxJSON, DataClass.class);