簡體   English   中英

序列化 avro 生成的 object 到 json 時出現 JsonMappingException

[英]JsonMappingException when serializing avro generated object to json

我使用 avro-tools 從 avsc 文件生成 java 類,使用:

java.exe -jar avro-tools-1.7.7.jar compile -string schema myfile.avsc 

然后我嘗試通過 ObjectMapper 將這些對象序列化為 json,但總是得到一個 JsonMappingException 說“不是枚舉”或“不是聯合”。 在我的測試中,我使用它的構建器或構造器創建了生成的 object。 我對不同類的對象有這樣的例外......

示例代碼:

ObjectMapper serializer = new ObjectMapper(); // com.fasterxml.jackson.databind
serializer.register(new JtsModule()); // com.bedatadriven.jackson.datatype.jts
...
return serializer.writeValueAsBytes(avroConvertedObject); // => JsonMappingException

我還嘗試了許多配置: serializer.configure(...) 但仍然失敗。 版本: Java 1.8,jackson-datatype-jts 2.3,jackson-core 2.6.5,jackson-databind 2.6.5,jackson-annotations 2.6.5

有什么建議么? 謝謝!

如果SCHEMA成員確實如此(我們沒有看到完整的錯誤消息),那么您可以將其關閉。 我使用 mixin 來做到這一點,就像這樣:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.avro.Schema;
import org.junit.Test;

import java.io.File;
import java.io.IOException;

public class AvroGenerTests
{
  abstract class IgnoreSchemaProperty
  {
    // You have to use the correct package for JsonIgnore,
    // fasterxml or codehaus
    @JsonIgnore abstract void getSchema();
  }

  @Test
  public void writeJson() throws IOException {
    BookAvro b = BookAvro.newBuilder()
      .setTitle("Wilk stepowy")
      .setAuthor("Herman Hesse")
      .build();
    ObjectMapper om = new ObjectMapper();
    om.enable(SerializationFeature.INDENT_OUTPUT);
    om.addMixIn(BookAvro.class, IgnoreSchemaProperty.class);
    om.writeValue(new File("plik_z_gen.json"), b);
  }
}

上一篇文章正確回答了這個問題。 我只是補充上一個答案。 我沒有將其寫入文件,而是在將其作為 POST 請求中的正文發送之前將其轉換為字符串。

public class AvroGenerateJSON
{
  abstract class IgnoreSchemaProperty
  {
    // You have to use the correct package for JsonIgnore,
    // fasterxml or codehaus
    @JsonIgnore abstract void getSchema();
  }

  public String convertToJson() throws IOException {
    BookAvro b = BookAvro.newBuilder()
      .setTitle("Wilk stepowy")
      .setAuthor("Herman Hesse")
      .build();
    ObjectMapper om = new ObjectMapper();
    om.enable(SerializationFeature.INDENT_OUTPUT);
    om.addMixIn(BookAvro.class, IgnoreSchemaProperty.class);
    String jsonString = om.writeValueAsString(b);
    return jsonString;
  }
}

https://www.programcreek.com/java-api-examples/?api=org.apache.avro.io.JsonEncoder找到代碼示例后,我編寫了一個方法來轉換任何給定的 Avro 對象(它們擴展了 GenericRecord)到一個 Json 字符串。 代碼:

import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.io.JsonEncoder;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

// ... Class header etc. ...

public static <T extends GenericRecord> String convertToJsonString(T event) throws IOException {

    String jsonstring = "";

    try {
        DatumWriter<T> writer = new GenericDatumWriter<T>(event.getSchema());
        OutputStream out = new ByteArrayOutputStream();
        JsonEncoder encoder = EncoderFactory.get().jsonEncoder(event.getSchema(), out);
        writer.write(event, encoder);
        encoder.flush();
        jsonstring = out.toString();
    } catch (IOException e) {
        log.error("IOException occurred.", e);
        throw e;
    }

    return jsonstring;
}

我的要求發生了變化,有人告訴我需要將 Avro 對象直接轉換為 JSON,而不保留任何元數據。 我在此處指定了一個方法 convertToJsonString 的另一個答案將整個 Avro 對象轉換為 JSON,以便使用解碼器可以將原始 Avro 對象重新創建為 Avro 對象。 那不是我的mgt。 不再想要了,所以我又回到了舊的繪圖板。

作為 Hail Mary 通行證,我嘗試使用 Gson,它可以完成我現在必須做的事情。 這很簡單:

 Gson gson = new Gson();
 String theJsonString = gson.toJson(object_ur_converting);

你已經完成了。

同意 Shivansh 的回答。 另外,在某些情況下,我們可能需要在其他類中使用 avro 生成的 pojo。 在底層,spring 使用 jackson 庫來處理這個問題,所以我們需要通過添加一個類來覆蓋全局 jackson 配置

@Configuration
public class JacksonConfiguration {
    public abstract IgnoreSchemaProperty {
          @JsonIgnore abstract void getSchema();
    }
    @Bean
    public ObjectMapper objectMapper() {
          ObjectMapper om = new ObjectMapper();
          om.addMixIn(SpecificRecordBase.class, IgnoreSchemaProperty.class);
          return om;
    }
}

SpecificRecordBase - 如果我們想從所有 avro 生成的類中忽略模式字段。 通過這種方式,我們可以序列化/反序列化我們的 avro 類並在我們的應用程序中的任何地方使用它而不會出現問題。

2022 Avro 字段名稱

abstract class IgnoreSchemaPropertyConfig {
   // You have to use the correct package for JsonIgnore,
   // fasterxml or codehaus
   @JsonIgnore
   abstract void getClassSchema();

   @JsonIgnore
   abstract void getSpecificData();

   @JsonIgnore
   abstract void get();

   @JsonIgnore
   abstract void getSchema();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM