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

Jackson ObjectMapper с произвольными ключами JSON

Я использую Jackson 1.9.5 в Android-проекте для разбора файлов JSON.

До сих пор у меня не было никаких проблем, и можно отлично разбирать файлы, используя следующий код:

AssetManager mgr = getAssets();
ObjectMapper mapper = new ObjectMapper();

try {
    InputStream ifp = mgr.open("detail_schema.json");
    schema = mapper.readValue(ifp, DetailSchema.class);
} catch (IOException e) {
    e.printStackTrace();
}

Если класс DetailSchema состоит из сочетания примитивных типов и классов. Я сейчас столкнулся с проблемой, когда я хочу разбирать JSON следующим образом:

"fields": {
    "Suburb": "Paddington",
    "State": "NSW",
    "Post Code": "2074",
    "Lollipop": "Foo Bar Haz"
}

Где я не могу знать ключи карты перед рукой (они могут быть определены пользователем). Таким образом, я не уверен, как должен выглядеть соответствующий класс Java.

Т.е., для этого примера это может выглядеть так:

public class MyClass {

    public String Suburb;
    public String State;
    public String PostCode;
    public String Lollipop;

}

Но это может быть неверно для другого экземпляра файла JSON. В идеале мне нужен какой-то способ для Джексона сопоставить значения с чем-то вроде NameValuePair. Я подозреваю, что автоматическое сопоставление объектов может не быть вариантом в этом случае - может кто-то подтвердить или опровергнуть это?

4b9b3361

Ответ 1

У вас есть два варианта. Либо вы можете использовать readTree в ObjectMapper, который возвращает JsonNode. Работа с JsonNode очень похожа на работу с деревом, поэтому вы можете получить дочерние узлы, прочитать значения и т.д.:

InputStream ifp = mgr.open("detail_schema.json");
JsonNode root = mapper.readTree(ifp);
JsonNode fields = root.get("fields");
for (JsonNode children : fields.getElements()) {
    // ...
}

Затем вам нужно будет вручную создать объект DetailSchema.

Или вы можете позволить Джексону десериализовать его как карту, и в этом случае вы будете использовать свой код, но где MyClass будет выглядеть следующим образом:

public class MyClass {
    public Map<String, Object> fields;

    // getter/setters
}

Вероятно, вы можете ввести значения карты как String, если вы уверены, что входы представляют собой текст в json. (На самом деле, я не уверен, какой тип исполнения Джексон делает, может быть, он все равно что-то разрешит...)