当前位置: 首页 > 知识库问答 >
问题:

从json到包含枚举的对象的反序列化问题

庄瀚玥
2023-03-14

使用jackson2.9.8对枚举反序列化有问题。Gson也可以正常工作。模型是从swagger api定义自动生成的

使用Gson,效果很好。对于杰克逊来说,它不适用于011、013和019,但适用于其他值

Swagger api定义的片段

服务代码: 类型: 字符串枚举: - “001” - “002” - “003” - “004” - “005” - “007” - “008” - “009” - “011” - “013” - “019”

自动生成的代码(删除getter/setter的易读性)

public class ProcessErrorTest1 {
    static String errorJson =
            "    {\n" +
            "      \"timestamp\": \"2019-07-29 11:55:48\",\n" +
            "      \"serviceCode\": \"019\",\n" +
            "      \"message\": \"service failed. \",\n" +
            "      \"rootException\": {\n" +
            "        \"source\": \"test\",\n" +
            "        \"reasonCode\": \"2131\",\n" +
            "        \"reasonText\": \"test\"\n" +
            "      }\n" +
            "}";

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        AppErrorResponse error = mapper.readValue(errorJson, AppErrorResponse.class);
       // Gson gson = new Gson();
        //AppErrorResponse error = gson.fromJson(errorJson, AppErrorResponse.class);
        System.out.println("error::" + error);
    }
}

public class AppErrorResponse {

  @SerializedName("message")
  private String message = null;

  @SerializedName("rootException")
  private ErrorResponse rootException = null;
  /**
   * Gets or Sets serviceCode
   */
  @JsonAdapter(ServiceCodeEnum.Adapter.class)
  public enum ServiceCodeEnum {
    _001("001"),
    _002("002"),
    _003("003"),
     _004("004"),
    _005("005"),
    _007("007"),
    _008("008"),
    _009("009"),
    _011("011"),
    _013("013"),
   // @JsonProperty("019") if add this , it works fine. But can't modify the auto generated code as it is available as jar
    _019("019");
  }
  @SerializedName("serviceCode")
  private ServiceCodeEnum serviceCode = null;

  @SerializedName("timestamp")
  private String timestamp = null;

}

public class ErrorResponse {

  @SerializedName("reasonCode")
  private String reasonCode = null;

  @SerializedName("reasonText")
  private String reasonText = null;

  @SerializedName("source")
  private String source = null;
}

jersey1:jackson生成的代码

import java.util.Objects;
import com.bt.consumer.appointment.dto.MAC2ErrorResponse;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
public class AppErrorResponse {
  @JsonProperty("message")
  private String message = null;

  @JsonProperty("rootException")
  private ErrorResponse rootException = null;

  public enum ServiceCodeEnum {
    _001("001"),
    _002("002"),
    _003("003"),
    _004("004"),
    _005("005"),
    _007("007"),
    _008("008"),
    _009("009"),
    _011("011"),
    _013("013"),
    _019("019");

    private String value;

    ServiceCodeEnum(String value) {
      this.value = value;
    }
    @JsonValue
    public String getValue() {
      return value;
    }

    @Override
    public String toString() {
      return String.valueOf(value);
    }
    @JsonCreator
    public static ServiceCodeEnum fromValue(String text) {
      for (ServiceCodeEnum b : ServiceCodeEnum.values()) {
        if (String.valueOf(b.value).equals(text)) {
          return b;
        }
      }
      return null;
    }

  }
  @JsonProperty("serviceCode")
  private ServiceCodeEnum serviceCode = null;

  @JsonProperty("timestamp")
  private String timestamp = null;
}

import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
public class ErrorResponse {
  @JsonProperty("reasonCode")
  private String reasonCode = null;

  @JsonProperty("reasonText")
  private String reasonText = null;

  @JsonProperty("source")
  private String source = null;
}

它适用于除 _011、_013 和 _019 之外的所有使用杰克逊错误 meessage:- com.fasterxml.jackson.databind.exc.InvalidFormatException:无法从字符串“011”中反序列化 ServiceCodeEnum 类型的值:值不是声明的枚举实例名称之一:[_011, _001, _002, _003, _004, _005, _007, _008, _009, _013, _019]

共有1个答案

包建义
2023-03-14

您的注释是针对Gson而不是Jackson的,您应该为Jackson而不是Gson生成pojos。行< code > @ JSON adapter(service code enum。Adapter.class)是为Gson处理该enum转换的适配器。

查看 swagger codegen 文档,您会发现有关生成 https://github.com/swagger-api/swagger-codegen#customizing-the-generator 的部分

据说:对于所有未指定的选项,将使用默认值。

上面列出了下表:

CONFIG OPTIONS
    modelPackage
        package for generated models

    apiPackage
        package for generated api classes
...... (results omitted)
    library
        library template (sub-template) to use:
        jersey1 - HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2
        jersey2 - HTTP client: Jersey client 2.6
        feign - HTTP client: Netflix Feign 8.1.1.  JSON processing: Jackson 2.6.3
        okhttp-gson (default) - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1
        retrofit - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)
        retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2)
        google-api-client - HTTP client: google-api-client 1.23.0. JSON processing: Jackson 2.8.9
        rest-assured - HTTP client: rest-assured : 3.1.0. JSON processing: Gson 2.6.1. Only for Java8

这一行可能是正在使用的:

< code>okhttp-gson(默认)- HTTP客户端:OkHttp 2.4.0。JSON处理:Gson 2.3.1

您需要指定一个使用 Jackson 的库和一个您想要的 HTTP 客户端。

 类似资料:
  • 问题内容: 我们使用Jackson 1.9.1对与Java对象之间的JSON请求响应字符串进行序列化和反序列化。原始Java类型,集合类型和自定义对象都可以(反)序列化而不会出现问题。但是,尝试将JSON字符串反序列化为Java枚举时遇到问题。JSON字符串的序列化方式如下: wt的Java类型如下所示: 我在SO上提到了this,this和this,并提出了重量单位的枚举,如下所示: 问题是,每

  • 我需要序列化/反序列化一个POJO包含一个特殊枚举(不是字符串的枚举)。我找到了很多字符串枚举的示例,但不是我的情况。 而不是: {“代码”:“20”,“消息”:“无效的URL参数值”,“说明”:“缺少应用程序标识符”} 编辑1 但我的结果是: 现在,我希望将改为

  • 为了确保在我的RESTful web服务中来回发送的数据不冗余,每个嵌套对象都只序列化了它的ID(消息的用户只序列化了用户ID,因为客户端和服务器都已经知道用户的所有详细信息)。 序列化工作正常,产生以下效果: 问题:反序列化不会生成仅具有其ID的嵌套对象。生成的反序列化嵌套对象为空。 以下是前面提到的消息和用户对象。序列化“策略”是从此处指定的第三个选项中使用的:如何仅序列化Jackson的子级

  • 问题内容: 我正在使用org.json库将Object转换为Json格式。请检查以下代码片段。 它显示了这样的输出: 它显示为空白并添加了卷曲基数。这是什么意思?有人遇到过这个问题吗? 问题答案: 首先,我强烈建议您不要使用此库(org.json),这是一个非常古老且不受支持的库(据我所知)。我建议杰克逊或格森。 但是,如果您确实需要JSONObject,则可以将getter添加到枚举中: 序列化

  • 问题内容: 我在Android上的Java中具有以下枚举,并且我希望能够将传入的JSON字符串/对象中的整数反序列化为此Enum类型。我一直在Jackson和GSON上受到欢迎,但在我正在使用的JSON.org包上却什么也没有。 有没有简单的方法可以做到这一点,或者我需要更改JSON解码器?谢谢。 问题答案: 将返回您的数组,然后可以遍历数组并检查

  • 我在Android上的Java中有以下枚举,我希望能够将传入的JSON字符串/对象中的整数反序列化为该枚举类型。我在杰克逊和GSON上得到了点击,但在json.org包上没有,我正在使用。 是否有一个简单的方法来做到这一点,或者我需要改变JSON解码器?谢了。