【问题标题】:How to serialize list of enums from rest api如何从rest api序列化枚举列表
【发布时间】:2019-05-14 03:26:32
【问题描述】:

我想从一个 rest api 调用中返回一个枚举列表,并让它以 JSON 格式显示枚举的值,而不仅仅是枚举名称。目前我的休息电话返回的 json 看起来像:

{
  "responses": [
    "ACTION_TAKEN",
    "IGNORED",
    "UNDETECTED"
  ]
}

但是,我希望它更像(或类似的东西):

{
  "responses": [
    {
      "name":"ACTION_TAKEN",
      "value":"Action Taken"
    },
    {
      "name":"IGNORED",
      "value":"Ignored"
    },
    {
      "name":"UNDETECTED",
      "value":"Undetected"
    }
   ]
}

我的枚举看起来像:

public enum Response {

  ACTION_TAKEN ("Action Taken"),
  IGNORED ("Ignored"),
  UNDETECTED("Undetected");

  private String value;

  Response(String value) {
    this.value = value;
  }

  public String getValue() {
    return this.value;
  }

  @Override
  public String toString() {
    return value;
  }
}

我的模型对象看起来像这样。为了这个例子,它只有一个枚举值列表。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class StaticData {

  private List<Response> responses;

  public List<Response> getResponses() {
    return responses;
  }

  public void setResponses(List<Response> responses) {
    this.responses = responses;
  }
}

web服务方法如下:

@Component
@Path("staticData")
@Produces("application/json")
@Consumes("application/json")
public class StaticDataResource {

  @GET
  public Response getCurrentContent() {
    StaticData staticData = new StaticData();
    staticData.setResponses(Arrays.asList(Response.values()));
    return Response.ok(staticData).build();
  }
}

这是我的有效 pom 中的依赖项(抱歉格式错误)

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.2.5.RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>com.sun.jersey.contribs</groupId>
    <artifactId>jersey-spring</artifactId>
    <version>1.19.1</version>
    <scope>compile</scope>
    <exclusions>
      <exclusion>
        <artifactId>*</artifactId>
        <groupId>org.springframework</groupId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>2.4</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.2.5.RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.2.5.RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>4.2.5.RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-oxm</artifactId>
    <version>4.2.5.RELEASE</version>
    <scope>compile</scope>
  </dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>4.2.5.RELEASE</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.19</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.19</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>19.0</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.reflections</groupId>
  <artifactId>reflections</artifactId>
  <version>0.9.10</version>
  <scope>compile</scope>
  <exclusions>
    <exclusion>
      <artifactId>guava</artifactId>
      <groupId>com.google.guava</groupId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.0.1</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.ws.rs</groupId>
  <artifactId>javax.ws.rs-api</artifactId>
  <version>2.0.1</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.eclipse.persistence</groupId>
  <artifactId>javax.persistence</artifactId>
  <version>2.1.0</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.ejb</groupId>
  <artifactId>javax.ejb-api</artifactId>
  <version>3.2</version>
  <scope>provided</scope>
</dependency>
  <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
      <scope>provided</scope>
    </dependency>
</dependencies>

我尝试将@JsonFormat(shape = JsonFormat.Shape.Object) 添加到我的枚举类的顶部。它没有用。我尝试在枚举类中的 getValue() 方法上方添加@JsonValue,但这也不起作用。我尝试添加一个扩展 StdSerializer 或 JsonSerializer 的自定义序列化程序,并使用 @JsonSerialize(using = ReasonSerializer) 在我的枚举上方引用该类。我在 serialize 方法中放了一个断点并没有命中它,所以这不起作用。我看了一点implements ContextResolver&lt;ObjectMapper&gt;,但不太明白这一点,或者这是否是正确的下坡路。

非常感谢任何帮助!谢谢!

【问题讨论】:

  • 这两个方法是什么返回Response.ok(staticData).build();

标签: java json rest serialization enums


【解决方案1】:

根据此页面: https://www.javaworld.com/article/2072870/java-enums-are-inherently-serializable.html 每个 Enum 都是自然可序列化的,所以你的 Enum 也应该可以工作。

但是,您应该考虑一下这里所说的内容: Is custom enum Serializable too?

总结: “枚举常量的序列化方式与普通可序列化或可外部化的对象不同。枚举常量的序列化形式仅由其名称组成;该常量的字段值不存在于表单中”

为了解决您的问题,我会考虑使用一个简单的 Pojo 类来表示您的可序列化类。如果您仍然想使用 Enum,那么您可以使用翻译 Pojo Enum (由于冗余,我不建议使用最后一个选项,但最后一个词应该是您的,具体取决于您想用它做什么: ) )。

【讨论】:

    【解决方案2】:

    最终解决方案

    这适用于 JAX-RS,我已经用你的代码对其进行了测试。

    @JsonFormatpublic String getName() 一起使用。

    @JsonFormat(shape=JsonFormat.Shape.OBJECT)
    public enum Response {
        ACTION_TAKEN ("Action Taken"),
        IGNORED ("Ignored"),
        UNDETECTED("Undetected");
    
        private String value;
    
        Response(String value) {
            this.value = value;
        }
        // Getters, Setters
    
        public String getName() {
            return name();
        }
    }
    

    JSON 输出

    {
        "responses": [{
                "value": "Action Taken",
                "name": "ACTION_TAKEN"
            }, {
                "value": "Ignored",
                "name": "IGNORED"
            }, {
                "value": "Undetected",
                "name": "UNDETECTED"
            }
        ]
    }
    

    使用以下依赖项进行测试。

    import com.fasterxml.jackson.annotation.JsonFormat;

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.6</version>
    </dependency>
    

    替代解决方案

    Jackson 文档指出,行为可能会根据所使用的序列化程序而改变。因此,如果第一个解决方案不起作用,那么这个解决方案可能会起作用。

    @JsonFormat(shape=JsonFormat.Shape.OBJECT)
    public enum Response {
        ACTION_TAKEN ("Action Taken"),
        IGNORED ("Ignored"),
        UNDETECTED("Undetected");
    
        private String name;
        private String value;
    
        Response(String value) {
            name = name();
            this.value = value;
        }
        
        public String getName() {
            return name;
        }
        
        public String getValue() {
            return value;
        }
    }
    

    【讨论】:

    • 我同意这可行,但不幸的是,它不能解决我的问题。我使用 Response.ok(staticData).build() 从 api 调用返回整个对象,而不是使用 writeValueAsString。
    • @Jessica 再次重写了我的答案。它现在应该适用于您的代码。请让我知道你的结果。 :)
    • 刚刚尝试了您的建议:将 JsonFormat 注释添加到枚举类,然后添加 getName 方法。它没有用。对我来说输出没有区别。
    • @Jessica 我将我正在使用的依赖项添加到答案中。看看这是否有所作为。确保导入相同。如果这没有帮助,您使用的是什么应用程序服务器以及什么版本?
    • @Jessica 还添加了一个可能更适合您的替代解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-02
    • 2021-11-28
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    相关资源
    最近更新 更多