jackson - how to serialize nested object with custom object names?

4.7k Views Asked by At

Here is an example:

class Person {

     String name;
     Address addressGiven;

     //getters and setters

    class Address {

     @JsonProperty(name="stno")
     private String StreetNo

     @JsonProperty(name="type")
     private AddressType addType;

     public void setstno(String stno){
     if (this.addressGiven==null)
            addressGiven=new Address();
     addressGiven.setStno(stno);
     }

    public void setType(String type) {
        if (addressGiven==null){
        addressGiven=new Address();
    }
    addressGiven.setType(AddressType.valueOf(type));
    }

    // other getters and setters
   }
}

AddressType.java

Enum AddressType {
HOME,
OFFICE,
BUSINESS,
DEFAULT;
}

Two points to note before I go to my question:

  1. Address in an inner class
  2. the instance attribute addType is of enum type

when I serialize the object:

Person person = new Person();
Person.setStNo("1234");
person.setType("HOME");

      ObjectMapper mapper = new ObjectMapper();
      String body = mapper.writeValueAsString(person);
      System.out.println(body);

I expect: 
    {
      "addressGiven: 
                 { "stno" : "1234",
                   "type" : HOME,
                 }
    }

but what I get is this :

{ "streetNo" : "1234"}.

Three noticable differences

  1. nested json is missing
  2. streetNo but not stno is returned
  3. No addressType is present.

why is the expected json (i.e inner not returned. am I missing some annotations anywhere? I browsed through jackson docs. but could not figure out sooner. so here I am?

1

There are 1 best solutions below

0
On

Jackson will automatically call the empty constructor on the object is serializing. the exception being if a constructor is annotated with @JsonCreator, or a builder class annotated with @JsonPOJOBuilder, and maybe another one im missing. i would remove the creation of Address and also the checking for null. dummy down those setters/getters.

ObjecMapper by default handles serialization of an Enum. i would suggest removing that manual conversion

@see DeserializationFeature.READ_ENUMS_USING_TO_STRING. default value is false which means that it uses Enum.valueOf to serialize the String into the correct value.

with all that being said, you are expecting something that doesnt match your code. Person does not have an attribute type, nor stNo. those are Address attributes. im curious to know how you get the output shown. see below for code and example output

class Person {
    private String name;
    private Address addressGiven;

    public void setName(String name) { this.name = name; }
    public void setAddressGiven(Address addressGiven) { this.addressGiven = addressGiven; }
    public String getName() { return name; }
    public Address getAddressGiven() { return addressGiven; }

    enum AddressType { HOME, OFFICE, BUSINESS, DEFAULT }
    static class Address {
        @JsonProperty("stno") private String streetNo;
        @JsonProperty("type") private AddressType addType;

        public String getStreetNo() { return streetNo; }
        public void setStreetNo(String streetNo) { this.streetNo = streetNo; }
        public AddressType getAddType() { return addType; }
        public void setAddType(AddressType addType) { this.addType = addType;}
    }

    public static void main(String[] args) throws JsonProcessingException {
        Person person = new Person();
        person.name = "joe";
        Address address = new Address();
        address.addType = AddressType.BUSINESS;
        address.streetNo = "010101";
        person.addressGiven = address;

        ObjectMapper mapper = new ObjectMapper();
        String body = mapper.writeValueAsString(person);
        System.out.println(body);
    }
}

{"name":"joe","addressGiven":{"stno":"010101","type":"BUSINESS"}}