Java 具有对象类型的 Jackson JSON 列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22917324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson JSON List with Object Type
提问by raoulsson
I have to serialize JSON from a list of Objects. The resulting JSON has to look like this:
我必须从对象列表中序列化 JSON。生成的 JSON 必须如下所示:
{
"status": "success",
"models": [
{
"model": {
"id": 23,
"color": "red"
}
},
{
"model": {
"id": 24,
"color": "green"
}
}
]
}
I am missing the type/key "model" when I simply serialize this:
当我简单地序列化它时,我缺少类型/键“模型”:
List<Model> list = new ArrayList<Model>(); // add some new Model(...)
Response r = new Response("success", list); // Response has field "models"
Instead I just get this:
相反,我只是得到这个:
{
"status": "success",
"models": [
{
"id": 23,
"color": "red"
},
{
"id": 24,
"color": "green"
}
]
}
How can I add "model" for each object without having to write a silly wrapper class with a property "model"?
如何为每个对象添加“模型”而不必编写带有属性“模型”的愚蠢包装类?
My classes look like this:
我的课程是这样的:
public class Response {
private String status;
private List<Model> models;
// getters / setters
}
public class Model {
private Integer id;
private String color;
// getters / setters
}
采纳答案by Sotirios Delimanolis
There's no built-in way to do this. You'll have to write your own JsonSerializer
. Something like
没有内置的方法可以做到这一点。您必须编写自己的JsonSerializer
. 就像是
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
然后注释该models
字段以便它使用它
@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.
如果您同时对其进行序列化和反序列化,则还需要一个自定义的反序列化器。
回答by coderatchet
This is an oldish question, But there is an arguably more idiomatic way of implementing this (I'm using Hymanson-databind:2.8.8
):
这是一个古老的问题,但有一种可以说是更惯用的实现方式(我正在使用Hymanson-databind:2.8.8
):
Define a ModelSerializer
(That extends StdSerializer
as recommended by Hymanson) that prints your model how you like and use the @JsonSerialize(contentUsing = ...)
over your collection type:
定义一个ModelSerializer
(StdSerializer
按照Hyman逊的建议扩展),以您喜欢的方式打印模型并使用@JsonSerialize(contentUsing = ...)
您的集合类型:
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 List
s of models but may apply this to Collection
s, Set
s, Native []
s and even the values of Map
s.
现在,您不仅限于List
模型的 s,还可以将其应用于Collection
s、Set
s、Native []
s 甚至 s 的值Map
。
回答by Decoded
Another approachis using StdConverter
class. Here is a working (abbreviated) example:
另一种方法是使用StdConverter
类。这是一个工作(缩写)示例:
// MyParentObject.java
import com.fasterxml.Hymanson.annotation.JsonProperty;
import com.fasterxml.Hymanson.databind.annotation.JsonDeserialize;
import com.fasterxml.Hymanson.databind.annotation.JsonSerialize;
public class MyParentObject {
@JsonSerialize(converter = ChildListToString.class)
@JsonDeserialize(converter = StringToChildList.class)
@JsonProperty
public List<AChildObject> myChildren;
}
// ChildListToString.java
import com.fasterxml.Hymanson.databind.util.StdConverter;
import java.util.List;
import java.util.stream.Collectors;
public class ChildListToString extends StdConverter<List<AChildObject>, String> {
@Override
public String convert(List<IntakeModuleUrn> value) {
// this is just as effective as using Hymanson "write array"
// Try-Catch omitted for brevity
StringBuilder builder = new StringBuilder("[");
value.stream().map(value -> new ObjectMapper().writeValue(value)).forEach(urnStr -> {
if(builder.length() > 1) {
builder.append(", ");
}
builder.append("\"").append(urnStr).append("\"");
});
builder.append("]");
return builder.toString();
}
}
// StringToChildList.java
import com.fasterxml.Hymanson.core.JsonParseException;
import com.fasterxml.Hymanson.core.type.TypeReference;
import com.fasterxml.Hymanson.databind.JsonMappingException;
import com.fasterxml.Hymanson.databind.ObjectMapper;
import com.fasterxml.Hymanson.databind.util.StdConverter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class StringToChildList extends StdConverter<String, List<AChildObject>> {
@Override
public List<AChildObject> convert(String value) {
// try - catch omitted here for brevity
List<String> strings = new ObjectMapper().readValue(value, new TypeReference<List<String>>() {});
return strings.stream()
.map(string -> {
return new ObjectMapper().readValue(string, AChildObject.class)
}).collect(Collectors.toList());
}
}
I like this because it gives you control of serialization and deserialization separately.
我喜欢这个因为它让你可以分别控制序列化和反序列化。