【问题标题】:Jackson JsonDeserializer always gets null valueJackson JsonDeserializer 总是得到空值
【发布时间】:2021-03-24 08:40:19
【问题描述】:

我正在使用 Camunda 工作流自动化,我想实现 JSON 序列化。

这里有一个示例项目:https://github.com/camunda/camunda-bpm-examples/tree/master/spin/dataformat-configuration-global

我做了所有相应的事情,但默认情况下,Jackson 无法序列化 MxSwiftMessage 对象(您可以在此处找到:https://github.com/prowide/prowide-iso20022/blob/develop/iso20022-core/src/main/java/com/prowidesoftware/swift/model/MxSwiftMessage.java)。

所以我不得不编写一个自定义的 JsonSerializer 和 JsonDeserializer。

我的问题是在反序列化器中我总是得到一个空字符串。

代码如下:

MxSwiftMessageJsonSerializer

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.prowidesoftware.swift.model.MxSwiftMessage;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

import static com.fasterxml.jackson.core.JsonToken.START_OBJECT;

public class MxSwiftMessageJsonSerializer extends StdSerializer<MxSwiftMessage> {

    private static final long serialVersionUID = 1L;

    public MxSwiftMessageJsonSerializer() {
        super(MxSwiftMessage.class);
    }

    @Override
    public void serializeWithType(MxSwiftMessage mxSwiftMessage, JsonGenerator gen,
                                  SerializerProvider provider, TypeSerializer typeSer)
            throws IOException, JsonProcessingException {
        WritableTypeId typeId = typeSer.typeId(mxSwiftMessage, START_OBJECT);
        typeSer.writeTypePrefix(gen, typeId);
        serialize(mxSwiftMessage, gen, provider); // call customized serialize method
        typeSer.writeTypeSuffix(gen, typeId);
    }

    @Override
    public void serialize(MxSwiftMessage mxSwiftMessage, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(mxSwiftMessage.getMessage());
    }
}

MxSwiftMessageJsonDeserializer

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.prowidesoftware.swift.model.MxSwiftMessage;

import java.io.IOException;

public class MxSwiftMessageJsonDeserializer extends JsonDeserializer<MxSwiftMessage> {

    @Override
    public MxSwiftMessage deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
        String xmlString = jsonParser.getValueAsString();
        return MxSwiftMessage.parse(xmlString);
    }
}

JacksonDataFormatConfigurator


import javax.xml.bind.JAXBElement;
import javax.xml.datatype.XMLGregorianCalendar;

import com.prowidesoftware.swift.model.MxSwiftMessage;
import org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormat;
import org.camunda.spin.spi.DataFormatConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

public class JacksonDataFormatConfigurator implements DataFormatConfigurator<JacksonJsonDataFormat> {

    private static final Logger logger = LoggerFactory.getLogger(JacksonDataFormatConfigurator.class);

    @Override
    public Class<JacksonJsonDataFormat> getDataFormatClass() {
        return JacksonJsonDataFormat.class;
    }

    @Override
    public void configure(JacksonJsonDataFormat dataFormat) {
        logger.info("Object mapper configuration started");
        ObjectMapper objectMapper = dataFormat.getObjectMapper();
        configureObjectMapper(objectMapper);
        logger.info("Configuration finished");
    }

    public static void configureObjectMapper(ObjectMapper objectMapper) {
        SimpleModule mxSwiftMessageSerializer = new SimpleModule();
        mxSwiftMessageSerializer.addSerializer(MxSwiftMessage.class, new MxSwiftMessageJsonSerializer());
        mxSwiftMessageSerializer.addDeserializer(MxSwiftMessage.class, new MxSwiftMessageJsonDeserializer());
        objectMapper.registerModule(mxSwiftMessageSerializer);
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.registerModule(createXMLGregorianCalendarSerializerModule());
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
        objectMapper.addMixIn(JAXBElement.class, JAXBElementMixIn.class);
    }

    public static SimpleModule createXMLGregorianCalendarSerializerModule() {
        SimpleModule module = new SimpleModule();
        module.addSerializer(XMLGregorianCalendar.class, new XMLGregorianCalendarSerializer());
        return module;
    }

}

依赖版本:

org.camunda.spin : 1.9.0

org.camunda.bpm : 7.12.0

com.fasterxml.jackson: 2.9.8

更新:

这个问题与使用 Camunda 密切相关。仅当进入具有 BPMN 类型的呼叫活动时才会出现此问题。我在 Camunda 论坛中发现了这一点,这表明我不是唯一遇到此错误的人: https://forum.camunda.org/t/call-activity-deserialization-error/14911

还有一张票(关闭状态):https://jira.camunda.com/browse/CAM-3754

但是我仍然没有找到任何解决方案。

【问题讨论】:

  • xmlString = jsonParser.getValueAsString(); 已经让我觉得是个错误。你应该得到一个 JSON 字符串而不是 XML,所以如果 MxSwiftMessage.parse(xmlString); 期望 XML 不应该工作。
  • 根据这个例子我不确定:github.com/camunda/camunda-bpm-examples/blob/master/spin/… 但它并没有解决我原来的问题:xmlString 为空
  • 自从我上次使用自定义反序列化程序已经很长时间了,但如果我没记错getValueAsXxxx() 返回当前标记的值,因此如果光标未位于具有值的标记处你什么也得不到(来自Javadoc:“如果无法将表示形式转换为字符串值(包括对象和数组等结构化类型以及空标记)”)。如果光标已经定位,您可以尝试getText()。
  • 谢谢你的回答,我刚刚试了一下,得到了NullPointerException for jsonParser.getText()
  • 好吧,假设 jsonParser 不为空,根据您之前的代码,它不应该是它不应该抛出 NPE。堆栈跟踪应该有助于确定那里实际上是空的,但我无法更深入地了解。您可以使用JsonParser 进行一些操作,例如尝试nextValue() 前进到下一个可能有值的标记,然后调用getText()。

标签: java json jackson camunda


【解决方案1】:

我终于找到了适合我的解决方案。魔法发生在serializeWithType 方法中。它必须将数据写入数组值。

我还将底层数据结构更改为 json 对象而不是纯字符串来存储 MxSwiftMessage 对象的 xml 表示形式。

这是代码:

MxSwiftMessageJsonSerializer

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.prowidesoftware.swift.model.MxSwiftMessage;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;

public class MxSwiftMessageJsonSerializer extends StdSerializer<MxSwiftMessage> {

    private static final long serialVersionUID = 1L;

    public MxSwiftMessageJsonSerializer() {
        super(MxSwiftMessage.class);
    }

    @Override
    public void serializeWithType(MxSwiftMessage mxSwiftMessage, JsonGenerator gen,
                                  SerializerProvider provider, TypeSerializer typeSer)
            throws IOException, JsonProcessingException {
        gen.writeStartArray();
        gen.writeString(MxSwiftMessage.class.getName());
        serialize(mxSwiftMessage, gen, provider);
        gen.writeEndArray();
    }

    @Override
    public void serialize(MxSwiftMessage mxSwiftMessage, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("message", mxSwiftMessage.getMessage());
        jsonGenerator.writeEndObject();
    }
}

MxSwiftMessageJsonDeserializer

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.prowidesoftware.swift.model.MxSwiftMessage;

import java.io.IOException;

public class MxSwiftMessageJsonDeserializer extends JsonDeserializer<MxSwiftMessage> {

    @Override
    public MxSwiftMessage deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
        String xmlString = node.get("message").asText();
        return MxSwiftMessage.parse(xmlString);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-01
    • 2022-09-29
    相关资源
    最近更新 更多