将avro生成的对象序列化为json时出现JsonMappingException

nhn9ugyo  于 2023-05-19  发布在  其他
关注(0)|答案(7)|浏览(232)

我使用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
有什么建议吗?谢谢!

igetnqfo

igetnqfo1#

如果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);
  }
}
yyhrrdl8

yyhrrdl82#

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();
}
jchrr9hc

jchrr9hc3#

我的请求被改变了,我被告知我需要将Avro对象直接转换为JSON,而不保留任何元数据。我在这里的另一个答案是指定了一个方法convertToJsonString将整个Avro对象转换为JSON,以便使用解编码器可以将原始Avro对象重新创建为Avro对象。这不是我的管理。所以我又回到了老画板上。
作为一个万福玛丽通行证,我尝试使用Gson和它的工作做我现在必须做的。很简单

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

你完了。

t5fffqht

t5fffqht4#

https://www.programcreek.com/java-api-examples/?api=org.apache.avro.io.JsonEncoder找到代码示例后,我编写了一个方法,该方法应该将任何给定的Avro对象(它们扩展了GenericRecord)转换为Json String。验证码:

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

uxh89sit5#

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

moiiocjp6#

我同意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生成的类中的schema字段。通过这种方式,我们可以序列化/反序列化我们的avro类,并在我们的应用程序中的任何地方使用它,而不会出现问题。

1rhkuytd

1rhkuytd7#

如果您在尝试通过logstash-logback-encoder使用结构化日志记录时遇到此问题。然后,您需要使用JsonFactoryDecorator实现来添加mixin,以忽略有问题的avro生成的getter。

package the.package.path;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.logstash.logback.decorate.JsonFactoryDecorator;
import org.apache.avro.specific.SpecificRecordBase;

public class AvroJsonFactoryDecorator implements JsonFactoryDecorator {
    abstract class JacksonIgnoreAvroProperties {

        @JsonIgnore
        public abstract org.apache.avro.Schema getClassSchema();

        @JsonIgnore
        public abstract org.apache.avro.specific.SpecificData getSpecificData();

        @JsonIgnore
        public abstract java.lang.Object get(int field$);

        @JsonIgnore
        public abstract org.apache.avro.Schema getSchema();
    }

    @Override
    public JsonFactory decorate(JsonFactory factory) {
        ObjectMapper objectMapper = (ObjectMapper) factory.getCodec();
        objectMapper.addMixIn(SpecificRecordBase.class, JacksonIgnoreAvroProperties.class);
        return factory;
    }
}

然后在logback配置中包含以下内容:

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="net.logstash.logback.encoder.LogstashEncoder">
                <jsonFactoryDecorator class="the.package.path.AvroJsonFactoryDecorator"/>
            </encoder>
        </appender>

相关问题