3

Lets say I have a list of objects like this: LinkedList<JsonAssessment> jsonAssessments....

It is returned to this kind of method:

@RequestMapping(value = "mapping", method = RequestMethod.POST)
public
@ResponseBody
List<JsonAssessment> doSomething(....) {
    .....
}

I am making AJAX call to this controller everything is working correctly as expected but I don't like the naming my JSON is returned. In firebug I am seeing:

{"LinkedList":[{"assessmentName":"........

The question is how can I rename that root element LinkedList? Is there any config I have to set?

EDIT

I do not want to use any wrapper objects.

EDIT

My ObjectMapper:

public class JsonObjectMapper extends ObjectMapper {

    public JsonObjectMapper() {
        super();
        this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
        this.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
        this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

}

Spring: 3.2.4.RELEASE Jackson: 2.1.2

EDIT

This object mapper is declared in MVC message converters:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="jsonObjectMapper"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

And that is what I've tried with naming strategy:

public class JsonPropertyNamingStrategy extends PropertyNamingStrategy {

    public static final MyNamingStrategy MY_NAMING_STRATEGY = new MyNamingStrategy();

    private static final LinkedHashMap<String, String> PROPERTIES = new LinkedHashMap<String, String>() {{
        put("LinkedList", "resultList");
    }};

    public static class MyNamingStrategy extends PropertyNamingStrategyBase {

        @Override
        public String translate(String propertyName) {
            if (propertyName == null) {
                return null;
            }

            if (PROPERTIES.containsKey(propertyName)) {
                return PROPERTIES.get(propertyName);
            }

            return propertyName;
        }

    }

}

I was debugging it and when it comes to translate method property names comes all except the root element. I have everything that LinkedList contains, but LinkedList is not coming to this method.

user2219247
  • 1,313
  • 10
  • 20
  • 26
  • Where are you wiring this ObjectMapper? Is this the one being used or is the Spring default one still in play? Also what have you tried regarding the `PropertyNamingStrategy`? That last part isn't really clear yet. (You only mention it doesn't work). – M. Deinum Sep 26 '13 at 10:51
  • Edited, please take a look. – user2219247 Sep 26 '13 at 10:59
  • Looking at the sources for Jackson the `PropertyNamingStrategy` isn't going to help as that is only used for properties and not root types. Judging from the source the `RootNameLookup` is handling the translation and that only allows for different naming by the use of annotations, else it will fallback to the classname. When using JAXB annotations jackson will use those for the metadata. – M. Deinum Sep 26 '13 at 11:13

3 Answers3

3

Instead of directly returning a the List, wrap it inside a ResponseEntity that will give you a response without a root element

@RequestMapping(value = "mapping", method = RequestMethod.POST)
public
@ResponseBody ResponseEntity<List<JsonAssessment>> doSomething(....) {
.....
return new ResponseEntity(yourList);
}

That way you don't have a root element. If you still want a root element you could add it to a Map. Results in the following JSON "[{"assessmentName":"........]

@RequestMapping(value = "mapping", method = RequestMethod.POST)
public
@ResponseBody ResponseEntity<Map<String, List<JsonAssessment>>> doSomething(....) {
.....
Map results = new HashMap();
result.put("assesments", yourlist);
return new ResponseEntity(results);
}

Should output {"assesments":[{"assessmentName":"........

Although you are stilling wrapping the objects here, it is in objects that are freely available, you don't have to add your own custom classes.

This is what we are using in a couple of our @Controllers, we are using Spring 3.2 and Jackson 2.2.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Thanks, but this is not a solutions for me. Using ResponseEntity in all of the methods can be avoid if you specify Serialization Feature to JSON Object mapper: `this.configure(SerializationFeature.WRAP_ROOT_VALUE, false);` (BTW false is default), and it will return you then JSON without root element, it will be `{"assesments":[{"assessmentName":"........`. But I need a root element, I just want to rename it without any wrappers. Unfortunately PropertyNamingStrategy is still not working for me. – user2219247 Sep 26 '13 at 10:42
  • How are you configuring the ObjectMapper? Post your configuration... Also please specify which Spring and Jackson version you are using. – M. Deinum Sep 26 '13 at 10:47
  • Edited the question, please take a look. – user2219247 Sep 26 '13 at 10:49
  • Any idea why `return new ResponseEntity(results);` gives this compile time error = `incompatible types: Map cannot be converted to HttpStatus` – Abhinav Dec 13 '13 at 04:25
0

put the list in a wrapper class is a a commonly implemented strategy

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
0

If you are using Jackson Mapper you can use Annotations to define names of properties in classes by

@JsonProperty("foo")

or set the order by

@JsonPropertyOrder({"foo", "bar"})

and so on.

See further Jackson Annotations

edit: Sorry, just saw the wrapper-comment. The only solution i saw is using a wrapper like this: How to rename root key in JSON serialization with Jackson

Community
  • 1
  • 1
schomax
  • 337
  • 2
  • 9
  • There also must be a way of doing this using PropertyNamingStrategy, the problem I am facing with it is that Spring MVC is handling it somehow differently than serializing something directly with ObjectMapper from JAXB objects. I am not getting 'LinkedList' root element property name in my naming strategy, while when serializing from JAXB objects, I am getting a root element of the object. – user2219247 Sep 26 '13 at 10:34