Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有对象类型的Jackson JSON列表_Java_Json_Serialization_Types_Jackson - Fatal编程技术网

Java 具有对象类型的Jackson 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,

我必须从对象列表中序列化JSON。生成的JSON必须如下所示:

{
    "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;
    // ...
}