Nic*_*las 7 java json jackson json-deserialization objectmapper
在将 Java 对象转换为 JSON 字符串时,我遇到了 JsonMappingException。以下是完整的异常消息。
com.fasterxml.jackson.databind.JsonMappingException: Not an array: {"type":"record","name":"ClearingSystemMemberIdentification2","namespace":"com.sam.eps.paymentdomain.avro.pacs002","doc":"Schema for com.sam.eps.iso.pacs002.ClearingSystemMemberIdentification2","fields":[{"name":"clearing_system_identification","type":["null",{"type":"record","name":"ClearingSystemIdentification2Choice","doc":"Schema for com.sam.eps.iso.pacs002.ClearingSystemIdentification2Choice","fields":[{"name":"code","type":["null",{"type":"string","avro.java.string":"String"}],"default":null},{"name":"proprietary","type":["null",{"type":"string","avro.java.string":"String"}],"default":null}]}],"default":null},{"name":"member_identification","type":["null",{"type":"string","avro.java.string":"String"}],"default":null}]} (through reference chain: com.sam.eps.paymentdomain.avro.pacs002.Document["fi_to_fi_payment_status_report"]->com.sam.eps.paymentdomain.avro.pacs002.FIToFIPaymentStatusReportV10["group_header"]->com.sam.eps.paymentdomain.avro.pacs002.GroupHeader91["instructed_agent"]->com.sam.eps.paymentdomain.avro.pacs002.BranchAndFinancialInstitutionIdentification6["financial_institution_identification"]->com.sam.eps.paymentdomain.avro.pacs002.FinancialInstitutionIdentification18["clearing_system_member_identification"]->com.sam.eps.paymentdomain.avro.pacs002.ClearingSystemMemberIdentification2["schema"]->org.apache.avro.Schema$RecordSchema["elementType"])
Run Code Online (Sandbox Code Playgroud)
下面是我用来将 Java 对象转换为 JSON 字符串的 java 代码。我尝试启用 ACCEPT_SINGLE_VALUE_AS_ARRAY、ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT 但仍然面临问题。不确定导致JsonMappingException 的原因:不是数组问题。
private String convertObjectToJson(Object request) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(OffsetDateTime.class, new JsonSerializer<OffsetDateTime>() {
@Override
public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(offsetDateTime));
}
});
simpleModule.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(DateTimeFormatter.ISO_LOCAL_DATE.format(localDate));
}
});
objectMapper.registerModule(simpleModule);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return objectMapper.writeValueAsString(request);
}
Run Code Online (Sandbox Code Playgroud)
当您使用 Avro 编译器从 Avro 模式自动生成 POJO 时,就会出现此问题。此自动生成的 POJO 包含以下额外字段等(除了用户在 Avro 架构中指定的字段)
public static final org.apache.avro.Schema SCHEMA$;
Run Code Online (Sandbox Code Playgroud)
由于 Avro API 中的一些错误,该Schema.getElementType()方法在序列化期间导致Not an array异常。下面是方法定义
public Schema getElementType() {
throw new AvroRuntimeException("Not an array: " + this);
}
Run Code Online (Sandbox Code Playgroud)
要解决此问题,只需在序列化期间忽略自动生成的 POJO 中的 SCHEMA$ 字段,如下所示
// create this class to ignore one or more fields
public abstract class IgnoreSchemaProperty
{
@JsonIgnore
abstract void getSchema();
}
public class Test{
public static void main(String args[]) {
ObjectMapper objectMapper=new ObjectMapper();
//pass the above created class in the mixIn
objectMapper.addMixIn(YourPojo.class, IgnoreSchemaProperty.class);
String pojoJson = objectMapper.writeValueAsString(YourPojo);
System.out.println(pojoJson);
}
}
Run Code Online (Sandbox Code Playgroud)
Jackson 转换过程递归地评估对象的每个字段或 getter,因此它可以创建 JSON 节点。
您可能正在此处转换生成的 AVRO 类型。它包含一个名为 的字段$SCHEMA,该字段本身没有名为 已getElementType()实现的方法。默认方法显式getElementType()抛出org.apache.avro.Schema此异常。由于 Jackson 在转换过程中遇到了这个方法,因此抛出了异常。
getElementType()只是该 Schema 类中默认抛出异常的许多默认实现之一。我认为没有任何办法可以解决这个问题,除了不使用 Jackson 创建 JSON,而是使用最初创建 AVRO 类型的相同 API。
编辑:也许您可以向映射器注册JsonSerializer<Schema>,并自己自定义架构的序列化。