JSON-RPC-десерилизация Джексона до универсального объекта - PullRequest
0 голосов
/ 14 февраля 2011

Я пытаюсь десериализовать объект JSON-RPC с Джексоном. Формат JSON-RPC:

{"result": "что-то", "error": null, "id": 1}

В моем случае свойство результата является универсальным объектом.

У меня есть класс для десериализации ответа:

public class JsonRpcResponse {

private Object result;
private JsonRpcError error;
private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public JsonRpcError getError() {
    return error;
}

public void setError(JsonRpcError error) {
    this.error = error;
}

public Object getResult() {
    return result;
}

public void setResult(Object result) {
    this.result = result;
}

}

Я могу получить объект ответа с помощью:

 JsonRpcResponse jsonResp = mapper.readValue(response, JsonRpcResponse.class);

Я хочу иметь универсальный метод, который десериализует этот объект результата, передавая методу тип объекта (или класса, если вы хотите), в который будет производиться десериализация. Таким образом, я могу передать любой тип объекта в зависимости от ожидаемого ответа.

Например, у меня есть этот класс с двумя свойствами:

public class JsonEventProperties {

private String conditon;
private String usage;

public JsonEventProperties(String condition, String usage) {
    this.conditon = condition;
    this.usage = usage;
}

public JsonEventProperties() {
    throw new UnsupportedOperationException("Not yet implemented");
}

public String getConditon() {
    return conditon;
}

public void setConditon(String conditon) {
    this.conditon = conditon;
}

public String getUsage() {
    return usage;
}

public void setUsage(String usage) {
    this.usage = usage;
}    

}

Объект результата внутри ответа для приведенного выше случая будет:

"result": {"condition":"test","usage":"optional"}

Я пытался:

mapper.readValue(result,objectClass)

где result - это экземпляр JsonNode результата (который по какой-то причине является LinkedHashMap) и objectClass - класс, к которому я хочу десериализоваться. Но это не работает.

Я весь день ломал голову над разными способами, но, вероятно, я не понимаю, кто работает Джексон.

Может кто-нибудь помочь мне с этим?

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 16 июня 2011

Я понимаю, что первоначальный вопрос касался полиморфной десериализации объекта "result".

У Джексона теперь есть встроенный механизм для этого, использующий аннотации @JsonTypeInfo и @JsonSubTypes.(ObjectMapper имеет методы, доступные в качестве альтернативы использованию аннотаций.) Дополнительная информация доступна в официальных документах на http://wiki.fasterxml.com/JacksonPolymorphicDeserialization. Кроме того, я опубликовал несколько примеров использования этого на http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html.

Однако, если вы застряли при десериализации JSON, который в целевом объекте не имеет элемента, идентифицирующего тип по какому-либо имени, то вы застряли с пользовательской десериализацией, где вам придетсяопределить на основе некоторого содержимого объекта, какой тип должен быть.Один из последних примеров в том же блоге, который я разместил выше, демонстрирует этот подход, использующий наличие определенных элементов JSON в целевом объекте для определения типа.

1 голос
/ 15 апреля 2011

Проверьте jsonrpc4j на github:

https://github.com/briandilley/jsonrpc4j

0 голосов
/ 17 ноября 2015

У меня была такая же проблема, это было мое решение.

Я добавил еще одно поле к объекту, поэтому при создании объекта я устанавливаю значение поля с именем класса, при десериализации его я использую mapper.convertvalue(object, Class.forName(field value)

В вашем случае private Object result;

В объекте результата добавьте еще одно поле "className", при сериализации класса установите значение "className" с именем класса, который вы рассматриваете как объект результата.

, в то время какдесериализация объекта JsonRpcResponse jsonResp = mapper.readValue(response, JsonRpcResponse.class);

в jsonResp у вас будет Object result, String className, здесь объект имеет тип связанныйhashmap

Теперь для преобразования в ваш объект

objectmapper.convertValue(result, Class.forName(className))

Приведенный выше код даст вам общий объект, который вы хотите.

Надеюсь, это поможет

...