Пользовательский десериализатор Джексона не может определить целевой класс - PullRequest
0 голосов
/ 05 октября 2011

У меня сейчас есть объект Join, для которого я пытаюсь написать собственный десериализатор.Мы храним ключ базы данных и имя класса Java объекта в JSON, и это выглядит примерно так:

{
    "@class": "com.mysite.data.ExpertFor",
    "id": "expert-for-1",
    "leftId": "user-profile-1",
    "leftType": "com.mysite.data.UserProfile",
    "rightId": "hotel-1",
    "rightType": "com.mysite.data.Hotel"
}

Мы делаем это, чтобы нам не нужно было сохранять фактический объект в базе данных.;скорее, мы получаем его, когда десериализуем.Проблема в том, что мой пользовательский сериализатор не может видеть элемент @class в потоке JSON - поэтому он не может правильно создать экземпляр нужного объекта после того, как все данные прочитаны.Вот мой десериализатор:

public Join deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
    Map<String, Object> values = new HashMap<String, Object>();

    // Loop through the JSON document and pull out all
    // the values and put them into the map
    JsonToken token = jp.nextToken();
    while (token != JsonToken.END_OBJECT) {
        logger.info("Non-data field: [" + token + "], name is [" + jp.getCurrentName() + "], text is [" + jp.getText() + "]");
        if (token == JsonToken.VALUE_STRING) {
            values.put(jp.getCurrentName(), jp.getText());
        }
        token = jp.nextToken();
    }         
    // remainder of code omitted for brevity
}    

Теперь строки Log4J, которые записываются в журналы, показывают все соответствующие элементы JSON, которые я ожидал, КРОМЕ элемента @class

Data field: [VALUE_STRING], name is [id], text is [expert-for-1]
Data field: [VALUE_STRING], name is [leftId], text is [user-profile-1]
Data field: [VALUE_STRING], name is [rightId], text is [hotel-1]
Data field: [VALUE_STRING], name is [leftType], text is [com.mysite.data.UserProfile]
Data field: [VALUE_STRING], name is [rightType], text is [com.mysite.data.Hotel]

Я попытался добавить аннотацию @JsonTypeInfo в свой класс, например

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") 

, но кажется, что элемент «проглатывается» кодом, и я не знаю, как это сделатьЭто.И мне это нужно, потому что любые потомки Join должны быть десериализованы.Вот некоторая дополнительная информация об иерархии, в которой находится этот класс:

Добавление аннотации @TypeInfo было сделано только для того, чтобы попытаться увидеть, что происходит.Я получаю одинаковое поведение, есть ли это там или нет.Что действительно странно, так это то, что мы используем эту же базовую функциональность в других классах, которые нуждаются в настраиваемой десериализации, и они прекрасно видят @class.Вот иерархия этого:

@JsonAutoDetect(value = JsonMethod.NONE)
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public abstract class TaggedObject implements Serializable {
...
}

и затем у нас есть DataObject

public abstract class DataObject extends TaggedObject {
...
}

, а затем у нас есть класс Join:

@JsonSerialize(using = Join.Serializer.class)
@JsonDeserialize(using = Join.Deserializer.class)
public abstract class Join<L, R> extends DataObject {
...
}

Я бы подумал@JsonTypeInfo будет унаследован от TaggedObject, но он здесь не виден, в то время как его видят другие классы в той же иерархии.

У всех есть идеи, как я могу получить класс этого объекта, поэтому яможно создать соответствующий объект?Что мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 30 июня 2017

с использованием модели дерева Джексона следующий код печатает недостающие @class:

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(jsonString);
Iterator<String> iterator = root.fieldNames();
while (iterator.hasNext()) {
    String fieldName = iterator.next();
    String fieldValue = root.get(fieldName).asText();
    System.out.println("name is [" + fieldName + "], text is [" + fieldValue + "]");
}

Выход:

name is [@class], text is [com.mysite.data.ExpertFor]
name is [id], text is [expert-for-1]
name is [leftId], text is [user-profile-1]
name is [leftType], text is [com.mysite.data.UserProfile]
name is [rightId], text is [hotel-1]
name is [rightType], text is [com.mysite.data.Hotel]
0 голосов
/ 12 октября 2011

Вы не должны пытаться вручную обрабатывать @class И объявлять, что он будет обрабатываться Джексоном с помощью @JsonTypeInfo - либо позволять Джексону полностью обрабатывать его (что он может и будет делать), либо удалять аннотации и обрабатывать вещи вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...