Jackson, deserialize class with private fields and arg-constructor without annotations Jackson, deserialize class with private fields and arg-constructor without annotations json json

Jackson, deserialize class with private fields and arg-constructor without annotations


Solution with mix-in annotations

You could use mix-in annotations. It's a great alternative when modifying the classes is not an option. You can think of it as kind of aspect-oriented way of adding more annotations during runtime, to augment the statically defined ones.

Assuming that your Person class is defined as follows:

public class Person {    private final String firstName;    private final String lastName;    private final int age;    public Person(String firstName, String lastName, int age) {        this.firstName = firstName;        this.lastName = lastName;        this.age = age;    }    // Getters omitted}

First define a mix-in annotation abstract class:

public abstract class PersonMixIn {    PersonMixIn(@JsonProperty("firstName") String firstName,                @JsonProperty("lastName") String lastName,                @JsonProperty("age") int age) {    }}

Then configure ObjectMapper to use the defined class as a mix-in for your POJO:

ObjectMapper mapper = new ObjectMapper();mapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);mapper.addMixIn(Person.class, PersonMixIn.class);

And deserialize the JSON:

String json = "{firstName: \"Foo\", lastName: \"Bar\", age: 30}";Person person = mapper.readValue(json, Person.class);


Since there is no default constructor, jackson or gson want create instance by there own. you should tell to the API how to create such instance by providing custom deserialize.

here an snippet code

public class PersonDeserializer extends StdDeserializer<Person> {     public PersonDeserializer() {        super(Person.class);    }     @Override    public Person deserialize(JsonParser jp, DeserializationContext ctxt)             throws IOException, JsonProcessingException {        try {            final JsonNode node = jp.getCodec().readTree(jp);            final ObjectMapper mapper = new ObjectMapper();            final Person person = (Person) mapper.readValue(node.toString(),                    Person.class);            return person;        } catch (final Exception e) {            throw new IOException(e);        }    }}

Then register simple module as to handle your type

final ObjectMapper mapper = jacksonBuilder().build();SimpleModule module = new SimpleModule();module.addDeserializer(Person.class, new PersonDeserializer());


Jackson provides the module jackson-modules-java8 for solve your problem.

You must built your ObjectMapper as following:

ObjectMapper mapper = new ObjectMapper()        .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)        .registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES));

You must add -parameters as compiler argument.

Example for maven:

 <plugin>       <groupId>org.apache.maven.plugins</groupId>       <artifactId>maven-compiler-plugin</artifactId>       <version>3.5.1</version>       <configuration>           <!--somecode-->           <compilerArgument>-parameters</compilerArgument>       </configuration> </plugin>

For gradle:

compileJava {  options.compilerArgs << "-parameters"}