当前位置: 首页 > 知识库问答 >
问题:

使用Jackson使用反序列化器正确反序列化对象

段干楚青
2023-03-14

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

我有一个restful Web服务,它有一个pojo作为参数。

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

所以我的类PreentivoWs需要一个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中添加enum,所有对象属性都被反序列化(email、cliente、partenza、destinazione等),但其他属性被忽略(dataritiro、dataconsegna、tipoconsegna)。

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

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

因此,当自定义反序列化器发生时,反序列化过程就结束了(甚至cliente对象也被中断)

共有1个答案

呼延升
2023-03-14

解决了的!如Jackson Wiki中所述:

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

因此,反序列化器中存在问题:当找到END\u对象(})时,必须停止,否则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情况下被移动,因为否则“}”标记将保留在流中,它将关闭枚举的父级。

因此需要将对象从{token解析为}token

 类似资料:
  • 根据这里描述的内容,我应该使用JSR-310表示而不是数字表示来序列化对象。但是,我得到了数字表示。可能有什么问题? 我是这样配置我正在使用的映射器的: 这是我得到的反序列化示例 对于以下事例类:

  • 我想将json反序列化到类Foo: IBar有两个实现,但是当反序列化时,我总是想使用第一个实现。(理想情况下,这将使问题变得更容易,因为不需要运行时类型检查) 我相信我可以编写自定义反序列化程序,但我觉得一定有更简单的方法。 我找到了这个注释,它在没有列表的情况下非常有效。

  • 我目前正在开发一个Java web应用程序,它使用Magento REST API公开的JSON数据。api返回的数据示例如下: 我的应用程序中有一个Java类,如下所示: 我想对数据进行反序列化,并将其转换为,但我总是得到以下错误: 这是我用来将JSON响应反序列化为ArrayList的语句行: 有人能分享一些见解吗?我看到一些例子,返回的JSON对象前面没有任何ID。那是因为我做错了什么吗?非

  • 我想反序列化表单中的类: 其中文本是加密的,反序列化应该在重建TestFieldEncryptedMessage实例之前取消对值的加密。 我采用的方法非常类似于:https://github.com/codesqueak/jackson-json-crypto 也就是说,我正在构建一个扩展SimpleModule的模块: 如您所见,设置了两个修饰符:EncryptedSerializerModif

  • 我想通过扩展默认的反序列化器来创建自己的反序列化器,在其后面设置更多的值: 如您所见,我还想将此DTO母类重用于其他DTO。 我没有找到任何这样的例子。我真的是世界上第一个 反序列化的“AsUsual”(p,ctxt)应该是什么 我应该使用什么motherclass?JsonDeserializer/StdDeserializer/UntypedObjectDeserializer 反序列化程序会

  • 如何将jackson JSON映射器与Java 8 LocalDateTime一起使用? JSONMappingException:无法从JSON字符串实例化类型[simple type,class java.time.LocalDateTime]的值;没有单字符串构造函数/工厂方法(通过引用链:mydto[“field1”]->subdto[“date”])