There's no built-in way to do this. You'll have to write your own JsonSerializer. Something like
class ModelSerializer extends JsonSerializer<List<Model>> {
@Override
public void serialize(List<Model> value, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
jgen.writeStartArray();
for (Model model : value) {
jgen.writeStartObject();
jgen.writeObjectField("model", model);
jgen.writeEndObject();
}
jgen.writeEndArray();
}
}
and then annotate the models field so that it uses it
@JsonSerialize(using = ModelSerializer.class)
private List<Model> models;
This would serialize as
{
"status": "success",
"models": [
{
"model": {
"id": 1,
"color": "red"
}
},
{
"model": {
"id": 2,
"color": "green"
}
}
]
}
If you're both serializing and deserializing this, you'll need a custom deserializer as well.
Answer from Sotirios Delimanolis on Stack OverflowThere's no built-in way to do this. You'll have to write your own JsonSerializer. Something like
class ModelSerializer extends JsonSerializer<List<Model>> {
@Override
public void serialize(List<Model> value, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
jgen.writeStartArray();
for (Model model : value) {
jgen.writeStartObject();
jgen.writeObjectField("model", model);
jgen.writeEndObject();
}
jgen.writeEndArray();
}
}
and then annotate the models field so that it uses it
@JsonSerialize(using = ModelSerializer.class)
private List<Model> models;
This would serialize as
{
"status": "success",
"models": [
{
"model": {
"id": 1,
"color": "red"
}
},
{
"model": {
"id": 2,
"color": "green"
}
}
]
}
If you're both serializing and deserializing this, you'll need a custom deserializer as well.
This is an oldish question, But there is an arguably more idiomatic way of implementing this (I'm using jackson-databind:2.8.8):
Define a ModelSerializer (That extends StdSerializer as recommended by Jackson) that prints your model how you like and use the @JsonSerialize(contentUsing = ...) over your collection type:
class ModelSerializer extends StdSerializer<Model> {
public ModelSerializer(){this(null);}
public ModelSerializer(Class<Model> t){super(t);} // sets `handledType` to the provided class
@Override
public void serialize(List<Model> value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
jgen.writeObjectField("model", value);
jgen.writeEndObject();
}
}
Meanwhile, in another file:
class SomethingWithModels {
// ...
@JsonSerialize(contentUsing = ModelSerializer.class)
private Collection<Model> models;
// ...
}
Now you aren't bound to just Lists of models but may apply this to Collections, Sets, Native []s and even the values of Maps.
How to de/serialize List<Object> with Jackson?
java - Jackson's ObjectMapper, serialize list - Stack Overflow
json - Java+Jackson : How to serialize a object containing array/list of other objects - Stack Overflow
Serializing list does not include type annotations
A Jackson ObjectMapper is relatively expensive to create, but once created it can be re-used for many conversions very cheaply. Your benchmark is flawed as it includes the ObjectMapper creation time in the measurement. A better benchmark would create one ObjectMapper up front, then perform several hundred or thousand conversions using the same mapper and calculate the average time per conversion. If you do this you'll see much more respectable numbers.
An ObjectMapper instance is thread-safe once fully configured, so it would be safe to do the following (exception handling code ignored for clarity)
public class X {
private static final ObjectMapper MAPPER = new ObjectMapper();
public static <T> String listToString(List<T> list) {
if(list == null) return null;
else return MAPPER.writeValueAsString(list);
}
}
It turned out that the problem was in debugger. If I do this in debug mode, it takes code 2-5 seconds to be executed. But if I do the same thing without debugger and log execution time, it is executed within 0,1-0,8 milliseconds - fast enough.