How to create a generic JsonDeserializer

I need to create a generic deserializer; in other words, I don't know what the deserialized target class will be.

I saw examples on the Internet where they create a deserializer, for example JsonDeserializer<Customer>, and then return new Customer(...)at the end. The problem is that I don't know what the return class will be.

I assume that I will need to use reflection to create an instance of the class and populate the field. How to do this from the deserialization method?

public class JsonApiDeserializer extends JsonDeserializer<Object> {

    @Override
    public Object deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {

        //Need to parse the JSON and return a new instance here
    }

}
+4
source share
6 answers

After some tests, I found that the @ jax answer has a problem.

@Staxman, createContextual() Deserializer, . , createContextual, . , 1 (, ), , targetClass , .

:

public class JsonApiDeserializer extends JsonDeserializer<Object> implements
        ContextualDeserializer {

    private Class<?> targetClass;

    public JsonApiDeserializer() {
    }

    public JsonApiDeserializer(Class<?> targetClass) {
        this.targetClass = targetClass;
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        Object clazz = targetClass.newInstance();
        //Now I have an instance of the annotated class I can populate the fields via reflection
        return clazz;
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
            BeanProperty property) throws JsonMappingException {
        //gets the class type of the annotated class
        targetClass = ctxt.getContextualType().getRawClass();
        //this new JsonApiDeserializer will be cached
        return new JsonApiDeserializer(targetClass);
    }
}
+1

, 2 , , Object Object[], :

- :

public class JsonApiDeserializer extends JsonDeserializer<Object> {
    @Override
    public Object deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        String text = jp.getText();
        if (text.startsWith("{"))
            return new ObjectMapper().readValue(text, Map.class);
        return new ObjectMapper().readValue(text, Map[].class);
    }
}

: Uncompiled untested

+1

ContextualDeserializer

public class JsonApiDeserializer extends JsonDeserializer<Object> implements
        ContextualDeserializer {

    private Class<?> targetClass;

    @SneakyThrows
    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        Object clazz = targetClass.newInstance();

        //Now I have an instance of the annotated class I can populate the fields via reflection

        return clazz;
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
            BeanProperty property) throws JsonMappingException {
        //gets the class type of the annotated class
        targetClass = ctxt.getContextualType().getRawClass();
        return this;
    }

}

, , DeserializationContext ctxt , null, ctxt.getContextualType().

- ?

+1

, , POJO JSON.

, , (, header ), Map .

, :

ObjectMapper mapper = new ObjectMapper();
Map<String, Object> userData = mapper.readValue(jsonData, Map.class);
0

, , , json , - :


ObjectMapper objectMapper = (ObjectMapper) jp.getCodec();
ObjectNode node = objectMapper.readTree(jp);
and then node.has("propertyName") so that you can create, setup and return your object and leave to the client of the deserialiser the responsibility of the cast.

" , , ".

, ,

0

, , JSON, .

  • JSON. , . , , .
  • factory, JSON. , , Object create (string typeFromJson, Map data). factory .

, , . # , Java .

, AFAIK, Jackson , @Post REST.

0

Source: https://habr.com/ru/post/1607275/


All Articles