Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.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 Json与jackson的动态反序列化_Java_Json_Serialization_Jackson - Fatal编程技术网

Java Json与jackson的动态反序列化

Java Json与jackson的动态反序列化,java,json,serialization,jackson,Java,Json,Serialization,Jackson,我已经看过问题“”,但它并没有真正回答我的问题 我想反序列化如下内容: public class Response<T> { private String status; private Error error; private T data; } 或 我希望将我的响应对象一般化如下: public class UserResponse extends Response<User> {} 最后,我创建了一个自定义反序列化程序。它可以工作,但我不

我已经看过问题“”,但它并没有真正回答我的问题

我想反序列化如下内容:

public class Response<T> {
    private String status;
    private Error error;
    private T data;
}

我希望将我的响应对象一般化如下:

public class UserResponse extends Response<User> {}
最后,我创建了一个自定义反序列化程序。它可以工作,但我不满意:

public class ResponseDeserializer extends JsonDeserializer<Response> {
@Override
public Response deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    Response responseData = new Response();
    Object data = null;

    for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
        String propName = jp.getCurrentName();
        // Skip field name:
        jp.nextToken();

        if ("contract".equals(propName)) {
            data = mapper.readValue(jp, Contract.class);
        } else if ("user".equals(propName)) {
            data = mapper.readValue(jp, User.class);
        } else if ("status".equals(propName)) {
            responseData.setStatus(jp.getText());
        } else if ("error".equals(propName)) {
            responseData.setError(mapper.readValue(jp, com.ingdirect.dg.business.object.community.api.common.Error.class));
        }
    }

    if (data instanceof Contract) {
        Response<Contract> response = new Response<Ranking>(responseData);
        return response;
    }

    if (data instanceof User) {
        Response<User> response = new Response<User>(responseData);
        return response;
    }

    // in all other cases, the type is not yet managed, add it when needed
    throw new JsonParseException("Cannot parse this Response", jp.getCurrentLocation());
}
公共类ResponseDeserializer扩展JsonDeserializer{
@凌驾
公共响应反序列化(JsonParser jp,反序列化上下文ctxt)引发IOException{
ObjectMapper mapper=新的ObjectMapper();
响应数据=新响应();
对象数据=null;
对于(;jp.getCurrentToken()!=JsonToken.END_对象;jp.nextToken()){
字符串propName=jp.getCurrentName();
//跳过字段名:
jp.nextToken();
如果(“合同”。等于(名称)){
data=mapper.readValue(jp,Contract.class);
}else if(“user”.equals(propName)){
data=mapper.readValue(jp,User.class);
}else if(“status”.equals(propName)){
responseData.setStatus(jp.getText());
}else if(“error”.equals(propName)){
setError(mapper.readValue(jp,com.ingdirect.dg.business.object.community.api.common.Error.class));
}
}
if(合同的数据实例){
响应=新响应(响应数据);
返回响应;
}
if(用户的数据实例){
响应=新响应(响应数据);
返回响应;
}
//在所有其他情况下,该类型尚未管理,请在需要时添加它
抛出新的JsonParseException(“无法解析此响应”,jp.getCurrentLocation());
}
}

有没有办法用注释来完成这项工作?提前谢谢

您是否尝试过:

public class AnyResponse {
    private String status;
    private Error error;
    private Contract contract;
    private User user;
    // And all other possibilities.
}
// ...
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
这将填充JSON中出现的任何对象,并将其余对象保留为空


然后,您可以使用相关对象填写响应。

Jackson框架提供了对动态类型的内置支持

//Base type
@JsonTypeInfo(property = "type", use = Id.NAME)
@JsonSubTypes({ @Type(ValidResponse.class), 
                @Type(InvalidResponse.class) 
              })
public abstract class Response<T> {

} 
//Concrete type 1
public class ValidResponse extends Response<T>{

}
//Concrete type 2
public class InvalidResponse extends Response<T>{

}

main {
    ObjectMapper mapper = new ObjectMapper();
    //Now serialize
    ValidResponse response = (ValidResponse)(mapper.readValue(jsonString,      Response.class));

    //Deserialize
    String jsonString = mapper.writeValueAsString(response);
}
//基类型
@JsonTypeInfo(property=“type”,use=Id.NAME)
@JsonSubTypes({@Type(ValidResponse.class)),
@类型(InvalidResponse.class)
})
公共抽象类响应{
} 
//混凝土类型1
公共类ValidResponse扩展了响应{
}
//混凝土类型2
公共类InvalidResponse扩展响应{
}
主要{
ObjectMapper mapper=新的ObjectMapper();
//现在连载
ValidResponse-response=(ValidResponse)(mapper.readValue(jsonString,response.class));
//反序列化
字符串jsonString=mapper.writeValueAsString(响应);
}

我就是这么做的。不过,谢谢你。
public class ResponseDeserializer extends JsonDeserializer<Response> {
@Override
public Response deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    Response responseData = new Response();
    Object data = null;

    for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
        String propName = jp.getCurrentName();
        // Skip field name:
        jp.nextToken();

        if ("contract".equals(propName)) {
            data = mapper.readValue(jp, Contract.class);
        } else if ("user".equals(propName)) {
            data = mapper.readValue(jp, User.class);
        } else if ("status".equals(propName)) {
            responseData.setStatus(jp.getText());
        } else if ("error".equals(propName)) {
            responseData.setError(mapper.readValue(jp, com.ingdirect.dg.business.object.community.api.common.Error.class));
        }
    }

    if (data instanceof Contract) {
        Response<Contract> response = new Response<Ranking>(responseData);
        return response;
    }

    if (data instanceof User) {
        Response<User> response = new Response<User>(responseData);
        return response;
    }

    // in all other cases, the type is not yet managed, add it when needed
    throw new JsonParseException("Cannot parse this Response", jp.getCurrentLocation());
}
public class AnyResponse {
    private String status;
    private Error error;
    private Contract contract;
    private User user;
    // And all other possibilities.
}
// ...
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//Base type
@JsonTypeInfo(property = "type", use = Id.NAME)
@JsonSubTypes({ @Type(ValidResponse.class), 
                @Type(InvalidResponse.class) 
              })
public abstract class Response<T> {

} 
//Concrete type 1
public class ValidResponse extends Response<T>{

}
//Concrete type 2
public class InvalidResponse extends Response<T>{

}

main {
    ObjectMapper mapper = new ObjectMapper();
    //Now serialize
    ValidResponse response = (ValidResponse)(mapper.readValue(jsonString,      Response.class));

    //Deserialize
    String jsonString = mapper.writeValueAsString(response);
}