【问题标题】:JsonMappingException when serializing avro generated object to json将avro生成的对象序列化为json时出现JsonMappingException
【发布时间】:2017-01-13 22:54:06
【问题描述】:

我使用 avro-tools 从 avsc 文件生成 java 类,使用:

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

然后我尝试通过ObjectMapper将这些对象序列化为json, 但总是得到一个 JsonMappingException 说“不是枚举”或“不是联合”。 在我的测试中,我使用它的构建器或构造器创建生成的对象。 对于不同类的对象,我得到了这样的例外......

示例代码:

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

有什么建议吗? 谢谢!

【问题讨论】:

  • 你找到解决这个问题的方法了吗?我也面临同样的问题。
  • 我也遇到了这个问题。
  • 是的,我解决了。关键是端到端使用一个库。我找到了一种将 avro-tools 也用于 json 序列化的方法。抱歉,我不能给你一个示例代码,因为这几天我在度假,我无法访问我的工作资源...... HTH
  • 我以不同的方式解决了这个问题。我将 avro 发行版中的速度模板复制到我的项目中,并在所有 SHEMA$ 属性和 getter 方法上添加了@com.fasterxml.jackson.annotation.JsonIgnore。
  • @Amir 是控制器的示例代码吗?

标签: java json serialization avro


【解决方案1】:

同意 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 类,并在应用程序的任何地方使用它,而不会出现问题。

【讨论】:

    【解决方案2】:

    我的要求发生了变化,我被告知我需要将 Avro 对象直接转换为 JSON,而不保留任何元数据。我在此处指定方法 convertToJsonString 的另一个答案将整个 Avro 对象转换为 JSON,以便使用解编码器可以将原始 Avro 对象重新创建为 Avro 对象。那不是我的管理。不再想要了,所以我又回到了旧的绘图板上。

    作为 Hail Mary 通行证,我尝试使用 Gson,它可以完成我现在必须做的事情。很简单:

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

    你已经完成了。

    【讨论】:

    • 评价最高的解决方案对我不起作用,我想是因为我在 avro 模式中有逻辑类型,并且我遇到了最后提到的异常。此解决方案完美运行.. 引起:org.apache.avro.AvroRuntimeException: Not an enum: {"type":"int","logicalType":"date"}
    【解决方案3】:

    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;
    }
    

    【讨论】:

      【解决方案4】:

      上一篇文章正确回答了这个问题。我只是补充上一个答案。我没有将其写入文件,而是将其转换为字符串,然后在 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;
        }
      }
      

      【讨论】:

        【解决方案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);
          }
        }
        

        【讨论】:

        • 这对我有用。感谢您的解决方案。对于任何希望在类层次结构中忽略相同方法的人,以下内容对我有用。 om.addMixIn(Object.class, IgnoreSchemaProperty.class)
        • 我尝试了类似的方法,但是我得到了 com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)
        • 我的 avro 架构有许多逻辑类型,即使遵循此解决方案,我也会收到此错误 - 原因:org.apache.avro.AvroRuntimeException: Not an enum: {"type":"int" ,"logicalType":"日期"}
        • 嗨,我知道我可能有点晚了,但是在按照确切的说明作为答案后,我遇到了“无限递归”问题。我必须做的唯一更改是在 MixIn 中为 SpecificData 添加另一个 @JsonIgnore。将以下行添加到 IgnoreSchemaProperty MixIn @JsonIgnore SpecificData getSpecificData()
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-06
        • 1970-01-01
        • 2017-08-05
        • 1970-01-01
        • 1970-01-01
        • 2013-05-11
        相关资源
        最近更新 更多