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. Я подозреваю, что автоматическое сопоставление объектов может не подходить в этом случае - может кто-нибудь подтвердить или опровергнуть это?


person aaronsnoswell    schedule 16.07.2012    source источник


Ответы (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) {
    // ...
}

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

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

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

    // getter/setters
}

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

person waxwing    schedule 16.07.2012
comment
На самом деле вам не нужно использовать специальный класс, чтобы получить Map, вы можете десериализовать Джексона непосредственно в реализацию интерфейса Map, например: Map jsonFields = mapper.readValue(ifp, HashMap.class) - person brianmearns; 09.09.2015