1

Just wondering if there was a way to do this - I have a class, something like

class MyClass {
    private String name;
    private String address;
    private String number;
}

When I serialise it to Json, using Jackson, I want to wrap the String variables together, so it would look something like

{
    "Strings": {
         "name" : "value",
         "address" : "value"
    }
 }

Without wrapping those variables in a List or Map class inside the MyClass... is this possible?

KingTravisG
  • 1,316
  • 4
  • 21
  • 43
  • 1
    You can wrap such fields in embedded object and call it "Strings". But it's really strange as for me. – yatul Jul 10 '13 at 09:47
  • So you want something that works for any class? – Bohemian Jul 10 '13 at 09:55
  • Well it should only be for one class, I just want to group everything together, so Strings would be wrapped in a "Strings": {}, ints in an "Integers" : {} and so on, but I can't have any of the array notations or anything enclosing it – KingTravisG Jul 10 '13 at 10:12
  • Perhaps you could also elaborate _why_ you want to do it? What benefit is there on client side? And if it's beneficial, why not structure your POJO same way? – StaxMan Jul 12 '13 at 00:31

5 Answers5

2

You can also add into your POJO class additional getters for "Strings", "Intigers", etc. Those methods should return Map's as a result. Consider below code:

import java.util.LinkedHashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonProgram {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        MyClass myClass = new MyClass();
        myClass.setAddress("New York, Golden St. 1");
        myClass.setName("James Java");
        myClass.setNumber("444");

        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(myClass));
    }
}

class MyClass {

    private String name;
    private String address;
    private String number;

    @JsonIgnore
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @JsonIgnore
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @JsonIgnore
    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @JsonProperty(value = "Strings")
    public Map<String, String> getStrings() {
        Map<String, String> map = new LinkedHashMap<String, String>();
        map.put("name", getName());
        map.put("address", getAddress());
        map.put("number", getNumber());
        return map;
    }
}

Result:

{
  "Strings" : {
    "name" : "James Java",
    "address" : "New York, Golden St. 1",
    "number" : "444"
  }
}

This is not, probably, the most elegant solution which you can use, but it is simple.

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
1

Jackson utilizes your class structure to decide about the json structure. If you need to wrap your class attributes in another attribute then you need to consider the wrapping. You don't need to create a collection if you don't need it. Simply put name and address in a different class and name that class as you desire the name for their wrapper. And then add instance of your wrapper class in your MyClass.

Juned Ahsan
  • 67,789
  • 12
  • 98
  • 136
  • 1
    Yeah I was trying to avoid doing that so was wondering if there was a way to achieve the same thing, but with avoiding all of the wrapper classes - I was trying to avoid the array notations around the Json values as well :( – KingTravisG Jul 10 '13 at 09:50
0

I use JsonSerializer to do this for me with Spring, it is very simple.

you create a class that extends JsonSerializer

like this one:

 public class ServerResposeSerializer extends JsonSerializer<ServerResponse> {
@Override
public void serialize(ServerResponse objectWrapper, JsonGenerator generator,
        SerializerProvider provider) throws IOException,
        JsonProcessingException {
    generator.writeStartObject();
    generator.writeNumberField("http_status", objectWrapper.getStatus().value());
    generator.writeStringField("message",objectWrapper.getMessage());
    generator.writeArrayFieldStart("objects");      
    List<?> objects = objectWrapper.getObjects();       
    for (Object object: objects)
    {
        generator.writeObject(object);
    }       
    generator.writeEndArray();
    generator.writeEndObject();
}

}

Annotate ServerResponse with the

@JsonSerialize (using = ServerResposeSerializer.class)

Now you can format any class you want to produce any kind of JSON String

Gleeb
  • 10,773
  • 26
  • 92
  • 135
0

A little bit old question, but while searching for a solution for the same problem i came across this answer.

Basicly create an ObjectWriter from ObjectMapper by using writer() function and then set the rootName for the mapping i.e

MyClass myclass = new MyClass()
myclass.setName("a");
myclass.setAddress("b");
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName("Strings");
String json = writer.writeValueAsString(myclass);

The output will be

{
   "Strings": {
     "name" : "a",
     "address" : "b"
    }  
}

note:

ObjectMapper is a threadsafe and the doc says it should be reuse when possible.

Community
  • 1
  • 1
oak
  • 2,898
  • 2
  • 32
  • 65
0
@Configuration
public class JacksonConfiguration {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
        mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
        //mapper.setSerializationInclusion(Include.NON_DEFAULT);
        return mapper;
    }

    
}
SQB
  • 3,926
  • 2
  • 28
  • 49
Shivakumar NH
  • 161
  • 1
  • 12