用Jackson序列化枚举

Nof*_*ate 88 java spring json spring-mvc jackson

我在下面有一个Enum desrcibed:

public enum OrderType {

  UNKNOWN(0, "Undefined"),
  TYPEA(1, "Type A"),
  TYPEB(2, "Type B"),
  TYPEC(3, "Type C");

  private Integer id;
  private String name;

  private WorkOrderType(Integer id, String name) {
    this.id = id;
    this.name = name;
  }

  //Setters, getters....
}
Run Code Online (Sandbox Code Playgroud)

我使用我的controller(new OrderType[] {UNKNOWN,TYPEA,TYPEB,TYPEC};)返回枚举数组,然后Spring将其序列化为以下json字符串:

["UNKNOWN", "TYPEA", "TYPEB", "TYPEC"] 
Run Code Online (Sandbox Code Playgroud)

迫使杰克逊像POJO一样序列化枚举的最佳方法是什么?例如:

[
  {"id": 1, "name": "Undefined"},
  {"id": 2, "name": "Type A"},
  {"id": 3, "name": "Type B"},
  {"id": 4, "name": "Type C"}
]
Run Code Online (Sandbox Code Playgroud)

我玩了不同的注释但无法获得这样的结果.

Nof*_*ate 87

最后我自己找到了解决方案

我不得不用枚举@JsonSerialize(using = OrderTypeSerializer.class)和实现自定义序列化器来注释枚举:

public class OrderTypeSerializer extends JsonSerializer<OrderType> {

  @Override
  public void serialize(OrderType value, JsonGenerator generator,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {

    generator.writeStartObject();
    generator.writeFieldName("id");
    generator.writeNumber(value.getId());
    generator.writeFieldName("name");
    generator.writeString(value.getName());
    generator.writeEndObject();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,要将Jackson配置为使用自定义(反)序列化处理,使用注释的替代方法是使用配置模块注册(反)序列化程序.http://wiki.fasterxml.com/JacksonHowToCustomSerializers (4认同)

Vec*_*nas 77

@JsonFormat(shape= JsonFormat.Shape.OBJECT)
public enum SomeEnum
Run Code Online (Sandbox Code Playgroud)

https://github.com/FasterXML/jackson-databind/issues/24开始提供

刚测试它适用于版本2.1.2

回答TheZuck:

我试过你的例子,得到了Json:

{"events":[{"type":"ADMIN"}]}
Run Code Online (Sandbox Code Playgroud)

我的代码:

@RequestMapping(value = "/getEvent") @ResponseBody
  public EventContainer getEvent() {
    EventContainer cont = new EventContainer();
    cont.setEvents(Event.values());
    return cont;
 }

class EventContainer implements Serializable {

  private Event[] events;

  public Event[] getEvents() {
    return events;
 }

 public void setEvents(Event[] events) {
   this.events = events;
 }
}
Run Code Online (Sandbox Code Playgroud)

和依赖是:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>${jackson.version}</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>${jackson.version}</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>${jackson.version}</version>
  <exclusions>
    <exclusion>
      <artifactId>jackson-annotations</artifactId>
      <groupId>com.fasterxml.jackson.core</groupId>
    </exclusion>
    <exclusion>
      <artifactId>jackson-core</artifactId>
      <groupId>com.fasterxml.jackson.core</groupId>
    </exclusion>
  </exclusions>
</dependency>

<jackson.version>2.1.2</jackson.version>
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个替代方案,它更干净,但是,我尝试了这个类并且类型没有被序列化,任何想法有什么问题?@JsonFormat(shape = JsonFormat.Shape.OBJECT)@JsonAutoDetect()public enum Event {VISIT_WEBSITE(Type.ADMIN); @JsonProperty公共类型; public Type getType(){return type; }事件(类型类型){this.type = type; } public enum Type {ADMIN,CONSUMER,}}我正在使用Jackson 2.1.2 (2认同)

lag*_*van 24

我找到了一个非常简洁的解决方案,当你不能像我的情况那样修改枚举类时特别有用.然后,您应该提供自定义的ObjectMapper,并启用某个功能.自Jackson 1.6以来,这些功能可用.

public class CustomObjectMapper extends ObjectMapper {
    @PostConstruct
    public void customConfiguration() {
        // Uses Enum.toString() for serialization of an Enum
        this.enable(WRITE_ENUMS_USING_TO_STRING);
        // Uses Enum.toString() for deserialization of an Enum
        this.enable(READ_ENUMS_USING_TO_STRING);
    }
}
Run Code Online (Sandbox Code Playgroud)

有更多与枚举相关的功能,请参见此处:

https://github.com/FasterXML/jackson-databind/wiki/Serialization-features https://github.com/FasterXML/jackson-databind/wiki/Deserialization-Features

  • 我同意.此外,在Jackson 2.5中,您不需要自定义对象映射器.就这样做:`objMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);`和这个:`objMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);` (4认同)

gav*_*koa 13

这是我的解决方案.我希望变换枚举{id: ..., name: ...}形成.

随着杰克逊1.x:

pom.xml中:

<properties>
    <jackson.version>1.9.13</jackson.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>${jackson.version}</version>
    </dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)

Rule.java:

import org.codehaus.jackson.map.annotate.JsonSerialize;
import my.NamedEnumJsonSerializer;
import my.NamedEnum;

@Entity
@Table(name = "RULE")
public class Rule {
    @Column(name = "STATUS", nullable = false, updatable = true)
    @Enumerated(EnumType.STRING)
    @JsonSerialize(using = NamedEnumJsonSerializer.class)
    private Status status;
    public Status getStatus() { return status; }
    public void setStatus(Status status) { this.status = status; }

    public static enum Status implements NamedEnum {
        OPEN("open rule"),
        CLOSED("closed rule"),
        WORKING("rule in work");

        private String name;
        Status(String name) { this.name = name; }
        public String getName() { return this.name; }
    };
}
Run Code Online (Sandbox Code Playgroud)

NamedEnum.java:

package my;

public interface NamedEnum {
    String name();
    String getName();
}
Run Code Online (Sandbox Code Playgroud)

NamedEnumJsonSerializer.java:

package my;

import my.NamedEnum;
import java.io.IOException;
import java.util.*;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

public class NamedEnumJsonSerializer extends JsonSerializer<NamedEnum> {
    @Override
    public void serialize(NamedEnum value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        Map<String, String> map = new HashMap<>();
        map.put("id", value.name());
        map.put("name", value.getName());
        jgen.writeObject(map);
    }
}
Run Code Online (Sandbox Code Playgroud)

随着杰克逊2.x:

pom.xml中:

<properties>
    <jackson.version>2.3.3</jackson.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.version}</version>
    </dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)

Rule.java:

import com.fasterxml.jackson.annotation.JsonFormat;

@Entity
@Table(name = "RULE")
public class Rule {
    @Column(name = "STATUS", nullable = false, updatable = true)
    @Enumerated(EnumType.STRING)
    private Status status;
    public Status getStatus() { return status; }
    public void setStatus(Status status) { this.status = status; }

    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public static enum Status {
        OPEN("open rule"),
        CLOSED("closed rule"),
        WORKING("rule in work");

        private String name;
        Status(String name) { this.name = name; }
        public String getName() { return this.name; }
        public String getId() { return this.name(); }
    };
}
Run Code Online (Sandbox Code Playgroud)

Rule.Status.CLOSED翻译成{id: "CLOSED", name: "closed rule"}.


小智 5

序列化 Enum 的一种简单方法是使用 @JsonFormat 注释。@JsonFormat 可以通过三种方式配置 Enum 的序列化。

@JsonFormat.Shape.STRING
public Enum OrderType {...}
Run Code Online (Sandbox Code Playgroud)

使用 OrderType::name 作为序列化方法。OrderType.TypeA 的序列化是“TYPEA”

@JsonFormat.Shape.NUMBER
Public Enum OrderTYpe{...}
Run Code Online (Sandbox Code Playgroud)

使用 OrderType::ordinal 作为序列化方法。OrderType.TypeA 的序列化是1

@JsonFormat.Shape.OBJECT
Public Enum OrderType{...}
Run Code Online (Sandbox Code Playgroud)

将 OrderType 视为 POJO。OrderType.TypeA 的序列化是{"id":1,"name":"Type A"}

JsonFormat.Shape.OBJECT是您的案例所需要的。

一种更复杂的方法是您的解决方案,为 Enum 指定一个序列化程序。

查看此参考:https : //fasterxml.github.io/jackson-annotations/javadoc/2.2.0/com/fasterxml/jackson/annotation/JsonFormat.html