【问题标题】:JsonMappingException: Not a map, not an array or not an enumJsonMappingException:不是地图,不是数组或不是枚举
【发布时间】:2020-06-27 10:44:20
【问题描述】:

我正在开发一个 rest api 应用程序,但我的代码有一些问题。我想返回一个扩展 avro 架构并将 HATEOAS 链接添加到响应的对象。我做了一些调查,结果发现我需要为对象自定义序列化程序。

有问题的部分代码是:

@JsonValue
public String serialize() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(this);
}

返回

无法编写 JSON:不是枚举。

当前对象是 avro 模式的扩展。我也试过了:

@JsonValue
public String serialize() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(getUserData());
}

返回:

无法写入 JSON:不是数组

其中用户数据是一个实际的 avro 对象。我不明白这些错误是什么意思。有人可以解释吗?另外,有没有更好的方法来返回一个结合其他参数的 avro 对象?

谢谢

编辑:

这里是完整的例子:

public class PaginatedUserData extends UserDataAvro {
    @JsonValue
    public String serialize() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        HashMap<String, String> map = new HashMap<>();
        map.put("test", "5");
        return mapper.writeValueAsString(map);
    }
}

返回:

无法写入 JSON:不是数组

【问题讨论】:

    标签: json spring-boot rest jackson jackson-databind


    【解决方案1】:

    @AvroGenerated 类(带有 Micronaut 框架的 Kotlin)中序列化 Kafka 消息时,我遇到了同样的问题。对我有用的是确保使用 Avro 序列化程序,如下所示:

        override fun getProperties() = mutableMapOf(
            "kafka.bootstrap.servers" to kafka.bootstrapServers,
            "kafka.producers.default.value.serializer" to KafkaAvroSerializer::class.java.name,
            "kafka.producers.default.key.serializer" to StringSerializer::class.java.name,
            "kafka.producers.default.schema.registry.url" to "mock://my-scope-name",
            "kafka.consumers.default.schema.registry.url" to "mock://my-scope-name",
            "kafka.consumers.default." + KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG to "true"
        )
    

    【讨论】:

      【解决方案2】:

      我遇到了类似的问题,并通过 Jackson-Mixin(来自 https://stackoverflow.com/a/7422285/702345)解决了它。 Avro 似乎生成了 Avro 特定的 Getter 方法,在 Jackson 序列化期间应始终忽略这些方法。

      public abstract class JacksonIgnoreAvroPropertiesMixIn {
      
        @JsonIgnore
        public abstract org.apache.avro.Schema getSchema();
      
        @JsonIgnore
        public abstract org.apache.avro.specific.SpecificData getSpecificData();
      }
      

      在 ObjectMapper 上比:

      objectMapper.addMixIn(
              org.apache.avro.specific.SpecificRecord.class, // Interface implemented by all generated Avro-Classes
              JacksonIgnoreAvroPropertiesMixIn.class);
      

      【讨论】:

      • 感谢您的回答。你从哪里得到objectMapper
      • 如果你有 spring-boot-starter-web 依赖,它应该已经在你的 Spring-Context 中。否则,只需调用构造函数:new com.fasterxml.jackson.databind.ObjectMapper()
      • @HaraldBrabenetz 这对我帮助很大!知道我如何仍然可以使用 JsonInclude.Include.NON_NULL 之类的东西吗?响应正在删除空值。
      【解决方案3】:

      杰克逊有时会出现问题。这些错误意味着 Spring Boot 期望的数据与您的结果不同。

      您应该返回具有 avro 模式作为属性的对象,如下所示:

      class UserResponse extends ResourceSupport {
        UserData userData;
        public void getUserData() { ... }
      }
      

      然后你在控制器中返回这个:

      return new UserResponse();
      

      如果这仍然不适合你,我建议你使用Gson。对于您的应用程序,它看起来像这样:

      Gson gson = new Gson();
      UserResponse data = new UserResponse();
      
      String json = gson.toJson(data.getUserData());
      

      【讨论】:

        猜你喜欢
        • 2016-03-27
        • 1970-01-01
        • 1970-01-01
        • 2014-07-24
        • 1970-01-01
        • 2023-01-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多