Reputation: 129
The class I'm serializing:
public class LogsDTO {
/** The logs. */
private List<LogDTO> logs;
/** Meta data. */
private Meta meta = new Meta();
// more
}
And the generated JSON:
{"LogsDTO":{"logs":[{"id":11,"archived":false}],"meta":{"totalPages":0}}}
I'd like my JSON to look like:
{"logs":[{"id":11,"archived":false}],"meta":{"totalPages":0}}
Is there a way to annotate so that this happens?
Thanks
Upvotes: 6
Views: 3518
Reputation: 6127
I solved it using a custom serializer,turning off global wrapping off, and turning on wrapping per class. It seems that even when you turn global wrapping off, Jackson adds wrapping for list elements of a class that has wrapping. One difference from your code is that for me the list was wrapped by its own class. It was something like this:
@JsonTypeName("interface")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) // wrapping per class instead of global in the mapper
public class InterfaceDTO
{
private InterfaceIpListDTO interfaceIpListDTO; // The list property for which I want to turn off wrapping
@JsonSerialize(using = com.tufin.securetrack.integration.rest.facade.serializer.InterfaceIPListWithoutWrapperNameSerializer.class) // Gonen
public InterfaceIpListDTO getInterfaceIpListDTO() {
return interfaceIpListDTO;
}
}
public class InterfaceIPListWithoutWrapperNameSerializer extends JsonSerializer<InterfaceIpListDTO>{
@Override
public void serialize(InterfaceIpListDTO interfaceIpListDTO, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartArray();
for (InterfaceIpDTO interfaceIpDTO : interfaceIpListDTO.getInterfaceIpDTOs()) {
jsonGenerator.writeObject(interfaceIpDTO);
}
jsonGenerator.writeEndArray();
}
}
Upvotes: 0
Reputation: 9197
Use Map of type Map<String, Object>
. This not really nice solution uses no Annotation. I just want to show other possibility how to do avoid json wrapping:
public static void main(String[] args) {
Map<String, Object> map = new HashMap<String, Object>();
List<LogDTO> logs = new ArrayList<LogDTO>();
logs.add(new LogDTO(1, true));
logs.add(new LogDTO(2, false));
logs.add(new LogDTO(3, true));
map.put("logs", logs);
map.put("meta", new Meta(33));
Gson gson = new GsonBuilder().create();
String json = gson.toJson(map);
LogsDTO dto = gson.fromJson(json, LogsDTO.class);
System.out.println(json);
System.out.println(dto);
}
produces:
{
"meta":{
"id":33
},
"logs":[
{
"id":1,
"archived":true
},
{
"id":2,
"archived":false
},
{
"id":3,
"archived":true
}
]
}
and
LogsDTO [logs=[Log [id=1, archived=true], Log [id=2, archived=false], Log [id=3, archived=true]], meta=Meta [id=33]]
Upvotes: 0
Reputation: 3250
@JsonRootName
: class annotation used to indicate name of "wrapper" entry used for root value, if root-wrapping is enabled.
Says in jackson docs : https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations
Related Jira Task: http://jira.codehaus.org/browse/JACKSON-630 1.9 and above versions supports it.
When investigate the source code of @JsonRootName,
They commented alwaysWrap method.
/* * Optional marker property that can be defined as
true
to force * wrapping of root element, regardless of whether globally * "root wrapping" is enabled or not. ** Note that value of
false
is taken to mean "use defaults", * and will not block use of wrapper if use is indicated by global features. * * @since 2.4 public boolean alwaysWrap() default false; */
They have a plan to activate it on v2.5
As of 2.4, one missing feature is property "alwaysWrap", which is hoped * to be added in 2.5, and would be used to force root name wrapping * for individual types.
Upvotes: 2