将对象转换为JSON字符串时发生JsonMappingException- org.apache.avro.AvroRuntimeException:不是数组:

tzdcorbm  于 2023-04-08  发布在  Apache
关注(0)|答案(3)|浏览(203)

在将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"])

下面是我用来将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);
    }
ocebsuys

ocebsuys1#

当您使用Avro编译器从Avro模式自动生成POJO时,会出现此问题。此自动生成的POJO包含以下额外字段(除了用户在Avro模式中指定的字段)

public static final org.apache.avro.Schema SCHEMA$;

由于Avro API中的一些bug,Schema.getElementType()方法在序列化过程中会导致Not an array异常,下面是方法定义

public Schema getElementType() {
    throw new AvroRuntimeException("Not an array: " + this);
  }

要修复此问题,只需在序列化期间忽略自动生成的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);
    }
}
yqhsw0fo

yqhsw0fo2#

Jackson转换过程递归地评估对象的每个字段或getter,因此它可以创建JSON节点。
您可能正在转换生成的AVRO类型。它包含一个名为$SCHEMA的字段,该字段本身没有实现一个名为getElementType()的方法。org.apache.avro.Schema的默认方法getElementType()显式抛出此异常。由于Jackson在转换过程中遇到此方法,因此抛出此异常。
getElementType()只是该Schema类中的许多默认实现之一,默认情况下会抛出异常。我不认为有任何方法可以绕过它,除了不使用Jackson创建JSON,而是使用最初创建AVRO类型的相同API。
编辑:也许你可以注册一个JsonSerializer<Schema>到你的Map器,并自定义Schema的序列化。

1aaf6o9v

1aaf6o9v3#

您可以使用JsonSerializer来检查Avro Schema代码:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.avro.Schema;

import java.io.IOException;

public class AvroSchemaSerializer extends JsonSerializer<Schema> {
    @Override
    public void serialize(Schema value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        String res = value.toString();
        jgen.writeRaw(res);
    }
}

相关问题