在json中找到具有不同类型值的相同键时,gson解析错误

时间:2018-10-22 14:59:43

标签: java android json parsing gson

从API(由Jackson生成)获取大型JSON响应,并且该对象仅在响应的第一次出现时才具有其值。第二次相同对象(具有相同密钥)到达时,将替换为某个数字/ ID。

JSON响应看起来像

[{id:1,Person:{name:"xyz",age:30}},
{id:2,Person:1}]

现在我想通过遵循GSON代码将整个响应存储在列表中

Type listType = new TypeToken<List<MainModel>>() {}.getType();
yourMainList = new Gson().fromJson(myres, listType);
//here myres is whole response and MainModel is my pojo class mapped with JSON response keys

但是当ID /数字重复的密钥第二次到达时,它给了我以下错误。

  

IllegalStateException:应为BEGIN_OBJECT,但在第1行第11935列的路径$ [1]处为NUMBER。在com.google.gson.stream.JsonReader.beginObject

有什么方法可以在Android中通过GSON解析此类JSON吗?

2 个答案:

答案 0 :(得分:0)

您需要确定如何处理Person类的不同变体。这是使用com.google.gson.JsonParser的最简单方法。

private void start() {
    String json = "[{id:1,Person:{name:\"xyz\",age:30}},\n" +
            "{id:2,Person:1}]";

    HashMap<Integer, Person> map = new HashMap<>();

    JsonArray items = new JsonParser().parse(json).getAsJsonArray();
    items.forEach(jsonElement -> {
        JsonObject jsonObject = jsonElement.getAsJsonObject();
        int id = jsonObject.get("id").getAsInt();
        JsonElement element = jsonObject.get("Person");
        if(element.isJsonObject()){
            JsonObject personObject = element.getAsJsonObject();
            Person person = new Person();
            person.name = personObject.get("name").getAsString();
            person.age = personObject.get("age").getAsInt();
            map.put(id, person);
        }
        else {
            int personValue = element.getAsInt();
            map.put(id, new Person(personValue));
        }
    });

    for (int id : map.keySet()) {
        Person person = map.get(id);
        Log.d("myTag", id + ", name: " + person.name + ", age: " + person.age);
    }
}

class Person{
    String name;
    int age;

    Person(){}

    Person(int personValue) {
        // decide how the object should look
    }
}

输出:

  

1,名字:xyz,年龄:30
  2,姓名:null,年龄:0

如果您希望以更通用的方式工作而不必用力键入字段名称,则可以使用Gson Custom Deserialization

答案 1 :(得分:0)

一种选择是对有问题的字段使用自定义JsonDeserializer,就像这样:

public class PersonDeSerializer implements JsonDeserializer<Person> {
    @Override
    public Person deserialize(JsonElement json, Type typeOfT, 
                JsonDeserializationContext context)
            throws JsonParseException {
        try {
            return context.deserialize(json, typeOfT);
        } catch (JsonSyntaxException e) {
            // return null to elave null or make whatever kind of a person
            return null;
        }
    }
}

然后您可以设置使用该适配器反序列化的问题字段,例如:

public class MainModel {
    private Long id;

    @JsonAdapter(PersonDeSerializer.class)
    private Person Person;  // should be person, but is Person in JSON
}