Java 具有对象类型的Jackson JSON列表
我必须从对象列表中序列化JSON。生成的JSON必须如下所示:Java 具有对象类型的Jackson JSON列表,java,json,serialization,types,jackson,Java,Json,Serialization,Types,Jackson,我必须从对象列表中序列化JSON。生成的JSON必须如下所示: { "status": "success", "models": [ { "model": { "id": 23, "color": "red" } }, { "model": { "id": 24,
{
"status": "success",
"models": [
{
"model": {
"id": 23,
"color": "red"
}
},
{
"model": {
"id": 24,
"color": "green"
}
}
]
}
public class Response {
private String status;
private List<Model> models;
// getters / setters
}
public class Model {
private Integer id;
private String color;
// getters / setters
}
当我简单地序列化时,我缺少类型/键“model”:
List<Model> list = new ArrayList<Model>(); // add some new Model(...)
Response r = new Response("success", list); // Response has field "models"
如何为每个对象添加“model”,而不必编写一个带有属性“model”的愚蠢包装类
我的课程是这样的:
{
"status": "success",
"models": [
{
"model": {
"id": 23,
"color": "red"
}
},
{
"model": {
"id": 24,
"color": "green"
}
}
]
}
public class Response {
private String status;
private List<Model> models;
// getters / setters
}
public class Model {
private Integer id;
private String color;
// getters / setters
}
公共类响应{
私有字符串状态;
私有列表模型;
//能手/二传手
}
公共类模型{
私有整数id;
私有字符串颜色;
//能手/二传手
}
没有内置的方法可以做到这一点。您必须编写自己的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();
}
}
这将序列化为
{
"status": "success",
"models": [
{
"model": {
"id": 1,
"color": "red"
}
},
{
"model": {
"id": 2,
"color": "green"
}
}
]
}
如果您同时对其进行序列化和反序列化,则还需要一个自定义反序列化程序。这是一个老生常谈的问题,但可以说有一种更惯用的实现方法(我使用的是
jackson databind:2.8.8
):
定义一个ModelSerializer
(根据Jackson的建议扩展了StdSerializer
),它可以按照您喜欢的方式打印您的模型,并在集合类型上使用@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();
}
}
class ModelSerializer扩展了StdSerializer{
公共ModelSerializer(){this(null);}
publicmodelserializer(Class t){super(t);}//将`handledType`设置为提供的类
@凌驾
public void序列化(列表值,JsonGenerator jgen,
SerializerProvider提供程序)引发IOException,
JsonProcessingException{
jgen.writeStartObject();
jgen.writeObject字段(“模型”,值);
jgen.writeEndObject();
}
}
同时,在另一个文件中:
class something with models{
// ...
@JsonSerialize(contentUsing=ModelSerializer.class)
私人收藏模式;
// ...
}
现在,您不必仅限于
列表
s模型,还可以将其应用于集合
s、集合
s、本机[]
s,甚至映射
s的值。另一种方法是使用StdConverter
类。以下是一个工作(缩写)示例:
//MyParentObject.java
导入com.fasterxml.jackson.annotation.JsonProperty;
导入com.fasterxml.jackson.databind.annotation.JsonDeserialize;
导入com.fasterxml.jackson.databind.annotation.JsonSerialize;
公共类MyParentObject{
@JsonSerialize(converter=ChildListToString.class)
@JsonDeserialize(converter=StringToChildList.class)
@JsonProperty
公共儿童名单;
}
//ChildListToString.java
导入com.fasterxml.jackson.databind.util.StdConverter;
导入java.util.List;
导入java.util.stream.collector;
公共类ChildListToString扩展了StdConverter{
@凌驾
公共字符串转换(列表值){
//这与使用Jackson“写入数组”一样有效
//为简洁起见,请尝试省略
StringBuilder=新的StringBuilder(“[”);
value.stream().map(value->newObjectMapper().writeValue(value)).forEach(urnStr->{
如果(builder.length()>1){
生成器。追加(“,”);
}
builder.append(\).append(urnStr.append(\);
});
生成器。追加(“]”);
返回builder.toString();
}
}
//StringToChildList.java
导入com.fasterxml.jackson.core.JsonParseException;
导入com.fasterxml.jackson.core.type.TypeReference;
导入com.fasterxml.jackson.databind.JsonMappingException;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.databind.util.StdConverter;
导入java.io.IOException;
导入java.net.URISyntaxException;
导入java.util.Collections;
导入java.util.List;
导入java.util.stream.collector;
公共类StringToChildList扩展了StdConverter{
@凌驾
公共列表转换(字符串值){
//为了简洁起见,这里省略了try-catch
List strings=new ObjectMapper().readValue(值,new TypeReference(){});
返回strings.stream()
.map(字符串->{
返回新的ObjectMapper().readValue(字符串,AChildObject.class)
}).collect(Collectors.toList());
}
}
我喜欢这样,因为它可以分别控制序列化和反序列化。您的JSON无效;必须引用对象成员名称(提示:“是有效的JSON对象成员名称”)能否显示您的
模型
类和响应
类?此代码不会编译。首先,您有一个名为value的参数,但正在编写“model”。另外,至少在我的jackson中,serialize的签名似乎只得到一个模型,而不是一个列表。
class SomethingWithModels {
// ...
@JsonSerialize(contentUsing = ModelSerializer.class)
private Collection<Model> models;
// ...
}