Search code examples
javajsonresttemplatepojo

Custom JSON to POJO mapper


Context

I am trying to receive data using RestTemplate GET request, the server returns the data that I need in JSON format, the response contains all data that I need, but it also contains a lot of excess data and I don't want to add excessive fields that will contain excessive data to my POJO to map it automatically.

The question is

Can I somehow make a custom mapper, to map only certain JSON fields to my java class? Would appreciate any help

Some code samples

Previously i mapped JSON straight to my POJO like this:

ResponseEntity<Foo> response = new RestTemplate(requestFactory)
            .exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<Foo>(){});

but now the service I am using changed its API and sends data in a totally different format. It would be really unpleasant to change my java classes, so I wonder if I can get to map only needed data

And the json i get looks like this:

[{
    "idReadable": "idR",
    "customFields": [{
        "projectCustomField": {
            "field": {
                "name": "Name",
                "$type": "type"
            },
            "$type": "type"
        },
        "value": {
            "name": "Value",
            "$type": "type"
        },
        "$type": "type"
    }],
    "id": "id",
    "$type": "type"
}]

and I need only two "name" values

The solution

As @mostneededrabbit suggested in comments the solution was to write custom Deserializer extending StdDeserializer for the RestTemplate inside of which looks something like this:

    ArrayNode nodeList = jp.getCodec().readTree(jp);
    HashMap<String, String> fields = new HashMap<>();
    List<Issue> foos = new ArrayList<>();

    for (JsonNode node : nodeList) {
        String id = node.get("id").asText();
        issues.add(new Foo(id));
    }

And to actually set it to work you would need to do something like this before sending the request:

    var mapper = new ObjectMapper();
    var module = new SimpleModule();
    module.addDeserializer(Foo.class, new FooDeserializer());
    mapper.registerModule(module);

    var converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(mapper);
    var restTemplate = new RestTemplate(requestFactory);
    restTemplate.getMessageConverters().add(0, converter);

Solution

  • You can ignore unneeded fields by putting this on top of your class:

    @JsonIgnoreProperties(ignoreUnknown = true)
    

    Then keep only the fields that are needed in the class.