Jackson JsonDeserializer 总是得到空值
Jackson JsonDeserializer always gets null value
我正在使用 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 类型进入调用 activity 时才会出现问题。我在 Camunda 论坛中发现了这个,这表明我不是唯一遇到此错误的人:
https://forum.camunda.org/t/call-activity-deserialization-error/14911
还有这个的ticket(关闭状态):https://jira.camunda.com/browse/CAM-3754
但是我仍然没有找到任何解决方案。
我终于找到了适合我的解决方案。魔术发生在 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);
}
}
我正在使用 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 类型进入调用 activity 时才会出现问题。我在 Camunda 论坛中发现了这个,这表明我不是唯一遇到此错误的人: https://forum.camunda.org/t/call-activity-deserialization-error/14911
还有这个的ticket(关闭状态):https://jira.camunda.com/browse/CAM-3754
但是我仍然没有找到任何解决方案。
我终于找到了适合我的解决方案。魔术发生在 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);
}
}