Saya memiliki Enum yang dideskripsikan di bawah ini:
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....
}
Saya mengembalikan enum array dengan controller ( new OrderType[] {UNKNOWN,TYPEA,TYPEB,TYPEC};
) saya, dan Spring membuat serialisasi menjadi string json berikut:
["UNKNOWN", "TYPEA", "TYPEB", "TYPEC"]
Apa pendekatan terbaik untuk memaksa Jackson membuat serial enum seperti POJO? Misalnya:
[
{"id": 1, "name": "Undefined"},
{"id": 2, "name": "Type A"},
{"id": 3, "name": "Type B"},
{"id": 4, "name": "Type C"}
]
Saya bermain dengan anotasi yang berbeda tetapi tidak bisa mendapatkan hasil seperti itu.
Jawaban:
Akhirnya saya menemukan solusinya sendiri.
Saya harus membuat anotasi enum dengan
@JsonSerialize(using = OrderTypeSerializer.class)
dan menerapkan serializer khusus: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(); } }
sumber
@JsonFormat(shape= JsonFormat.Shape.OBJECT) public enum SomeEnum
tersedia sejak https://github.com/FasterXML/jackson-databind/issues/24
baru saja mengujinya berfungsi dengan versi 2.1.2
jawaban untuk TheZuck :
Saya mencoba contoh Anda, dapatkan Json:
{"events":[{"type":"ADMIN"}]}
Kode saya:
@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; } }
dan dependensinya adalah:
<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>
sumber
@JsonFormat
enum saat digunakan di entitas lain? misalnya entitas di mana saya ingin enum harus berseri sebagai string, bukan sebagai objek. saya mencoba untuk menambahkan lain@JsonFormat
di lapangan di kelas yang menggunakan enum tetapi selalu serial sebagai objek.Saya telah menemukan solusi yang sangat bagus dan ringkas, terutama berguna ketika Anda tidak dapat memodifikasi kelas enum seperti dalam kasus saya. Kemudian Anda harus menyediakan ObjectMapper khusus dengan fitur tertentu yang diaktifkan. Fitur tersebut tersedia sejak 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); } }
Ada lebih banyak fitur terkait enum yang tersedia, lihat di sini:
https://github.com/FasterXML/jackson-databind/wiki/Serialization-features https://github.com/FasterXML/jackson-databind/wiki/Deserialization-Features
sumber
objMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
dan ini:objMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
Inilah solusi saya. Saya ingin mengubah enum menjadi
{id: ..., name: ...}
bentuk.Dengan Jackson 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>
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; } }; }
NamedEnum.java:
package my; public interface NamedEnum { String name(); String getName(); }
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); } }
Dengan Jackson 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>
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(); } }; }
Rule.Status.CLOSED
diterjemahkan ke{id: "CLOSED", name: "closed rule"}
.sumber
Cara mudah untuk membuat serial Enum menggunakan anotasi @JsonFormat. @JsonFormat dapat mengkonfigurasi serialisasi Enum dalam tiga cara.
@JsonFormat.Shape.STRING public Enum OrderType {...}
menggunakan OrderType :: name sebagai metode serialisasi. Serialisasi OrderType.TypeA adalah
“TYPEA”
@JsonFormat.Shape.NUMBER Public Enum OrderTYpe{...}
menggunakan OrderType :: ordinal sebagai metode serialisasi. Serialisasi OrderType.TypeA adalah
1
@JsonFormat.Shape.OBJECT Public Enum OrderType{...}
memperlakukan OrderType sebagai POJO. Serialisasi OrderType.TypeA adalah
{"id":1,"name":"Type A"}
JsonFormat.Shape.OBJECT adalah yang Anda butuhkan dalam kasus Anda.
Cara yang sedikit lebih rumit adalah solusi Anda, menentukan serializer untuk Enum.
Lihat referensi ini: https://fasterxml.github.io/jackson-annotations/javadoc/2.2.0/com/fasterxml/jackson/annotation/JsonFormat.html
sumber
Gunakan anotasi @JsonCreator, buat metode getType (), bersambung dengan toString atau objek yang berfungsi
{"ATIVO"}
atau
{"type": "ATIVO", "descricao": "Ativo"}
...
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeType; @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum SituacaoUsuario { ATIVO("Ativo"), PENDENTE_VALIDACAO("Pendente de Validação"), INATIVO("Inativo"), BLOQUEADO("Bloqueado"), /** * Usuarios cadastrados pelos clientes que não possuem acesso a aplicacao, * caso venham a se cadastrar este status deve ser alterado */ NAO_REGISTRADO("Não Registrado"); private SituacaoUsuario(String descricao) { this.descricao = descricao; } private String descricao; public String getDescricao() { return descricao; } // TODO - Adicionar metodos dinamicamente public String getType() { return this.toString(); } public String getPropertieKey() { StringBuilder sb = new StringBuilder("enum."); sb.append(this.getClass().getName()).append("."); sb.append(toString()); return sb.toString().toLowerCase(); } @JsonCreator public static SituacaoUsuario fromObject(JsonNode node) { String type = null; if (node.getNodeType().equals(JsonNodeType.STRING)) { type = node.asText(); } else { if (!node.has("type")) { throw new IllegalArgumentException(); } type = node.get("type").asText(); } return valueOf(type); } }
sumber
Di Spring Boot 2, cara termudah adalah dengan mendeklarasikan di application.properties Anda:
spring.jackson.serialization.WRITE_ENUMS_USING_TO_STRING=true spring.jackson.deserialization.READ_ENUMS_USING_TO_STRING=true
dan tentukan metode toString () dari enum Anda.
sumber