JsonMappingException:不是地图,不是数组或不是枚举

Posted

技术标签:

【中文标题】JsonMappingException:不是地图,不是数组或不是枚举【英文标题】:JsonMappingException: Not a map, not an array or not an enum 【发布时间】: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:不是数组

【问题讨论】:

【参考方案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://***.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());

【讨论】:

以上是关于JsonMappingException:不是地图,不是数组或不是枚举的主要内容,如果未能解决你的问题,请参考以下文章

JsonMappingException:无法初始化代理 - 没有会话

Spring cloud netflix 和 HystrixObservable --> JsonMappingException

使用 Pageable 字段测试端点时出现 JsonMappingException

自定义异常类jackson序列化jsonMappingException异常

JPA:多对多关系 - JsonMappingException:无限递归

com.fasterxml.jackson.databind.JsonMappingException