首页 文章

用 Jackson 的解串器正确地反序列化一个对象

提问于
浏览
0

我需要一个自定义反序列化器来在复杂的POJO中转换字符串 . 反序列化一直有效,直到使用反序列化器:特别是当使用自定义反序列化器时,我的对象的非对象属性不会被序列化 .

我有一个宁静的Web服务,它有一个pojo作为参数 .

public PreventivoResponse calculate(@FormParam(value = "preventivo") PreventivoWs preventivo) throws Exception;

所以我的 class PreventivoWs需要 fromString(String) 方法 . 这里的类定义:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PreventivoWs implements Serializable{
    private static final long serialVersionUID = -554141724349909424L;
    private ClienteMultiSelect cliente;

    private String riferimento;
    private List<EmailWS> email;

    private String dataritiro;
    private String dataconsegna;
    private Long tipoconsegna;

    private IndirizzoWS partenza;

    private IndirizzoWS destinazione;

    List<ColloWs> colli;

    HashMap<Long, String> services;

...
}

在jsonObject里面我有一个枚举定义为

{
  "value" : "A",
  "text"  : "Active"
}

但是这个对象需要转换反序列化器:

public class TipoPersonaFGJsonDeserializer extends JsonDeserializer<TipoPersonaFG> {

@Override
public TipoPersonaFG deserialize(JsonParser jsonParser, DeserializationContext context) 
        throws IOException, JsonProcessingException {

    JsonToken currentToken = null;
    while ((currentToken = jsonParser.nextValue()) != null) {
        switch (currentToken) {
            case VALUE_STRING:
                switch (jsonParser.getCurrentName()) {
                    case "value":
                        String name = jsonParser.getText();
                        return TipoPersonaFG.valueOf(name);
                }
                break;
            default:
                break;
        }
    }
    return null;
}
}

它在房产上注明:

@JsonDeserialize(using = TipoPersonaFGJsonDeserializer.class)
private TipoPersonaFG tipo;

fromString方法只需调用jackson ObjectMapper:

public static PreventivoWs fromString(String jsonString) throws IOException{
    ObjectMapper mapper = new ObjectMapper();
    PreventivoWs oggetto = mapper.readValue(jsonString, PreventivoWs.class);
    return oggetto;
}

如果没有在jsonString中指定枚举,它可以正常工作:对象被完美地反序列化;如果我在jsonString中添加枚举,则反序列化所有对象属性(email,cliente,partenza,destinazione,...),但忽略其他属性(dataritiro,dataconsegna,tipoconsegna) .

为什么?自定义解串器打破了反序列化的标准过程?

更新:解析过程在自定义反序列化器发生时被中断:我在json对象的末尾移动了 cliente 属性(包含特定的枚举):现在,字段dataconsegna,dataritiro等被反序列化 .

因此,当自定义反序列化器发生时(即使客户对象被中断),反序列化过程也会结束

1 回答

  • 0

    解决了!如Jackson Wiki所述:

    不得处理超出反序列化值的任何令牌(不多也不少)

    所以问题出在解串器中:你必须在找到END_OBJECT(})时停止,否则jsonParser继续直到流的结尾,消耗掉所有其他令牌 .

    @Override
    public TipoPersonaFG deserialize(JsonParser jsonParser, DeserializationContext context) 
            throws IOException, JsonProcessingException {
    
        JsonToken currentToken = null;
        String name = null;
        while ((currentToken = jsonParser.nextValue()) != null) {
            switch (currentToken) {
                case VALUE_STRING:
                    switch (jsonParser.getCurrentName()) {
                        case "value":
                            name = jsonParser.getText();
                            break;
                    }
                    break;
                case END_OBJECT:
                    if(name != null)
                        return TipoPersonaFG.valueOf(name);
                    else 
                        return null;
            }
        }
        return TipoPersonaFG.valueOf(name);
    }
    

    我添加了大小写条件END_OBJECT,仅消耗了第一个'}'并正确关闭了枚举对象的解析 . 返回在END_OBJECT情况下移动,否则'}'令牌将保留在流中,它将关闭枚举的父级 .

    因此,您需要将对象从“{”标记解析为“}”标记

相关问题