[英]How to deserialize Enum with Jackson?
用戶將{"lang": ["en_US", "en_UK"]}
發送到 REST API。我想填寫一個具有此屬性的 object List<EnmLanguage> lang;
. 除 JSON arrays 外,其他所有東西都有效。
我的 EnmLanguage.java 是:
@JsonSerialize(
using = BaseEnumSerializer.class
)
@JsonDeserialize(
using = BaseEnumDeserializer.class
)
public enum EnmLanguage implements BaseEnum, Serializable {
en_US {
public String getCode() {
return "en_US";
}
public String getText(EnmLanguage s) {
return s == EnmLanguage.en_US ? "English" : "İngilizce";
}
},
我的 BaseEnum.java 是:
public interface BaseEnum {
Object getCode();
String getText(EnmLanguage lang);
default String getText() {
return this.getText(EnmLanguage.tr_TR);
}
default Map<String, Object> getMap(EnmLanguage lang) {
return new HashMap<String, Object>() {
{
this.put("name", BaseEnum.this.getText(lang));
this.put("id", BaseEnum.this.getCode());
}
};
}
default Map<String, Object> getMap() {
return this.getMap(EnmLanguage.tr_TR);
}
static <T extends Enum<T> & BaseEnum> T fromCode(Class<T> parent, Object code) {
Map<Object, T> lookup = new HashMap();
Enum[] var3 = (Enum[])parent.getEnumConstants();
int var4 = var3.length;
for(int var5 = 0; var5 < var4; ++var5) {
T d = var3[var5];
lookup.put(((BaseEnum)d).getCode().toString(), d);
}
return (Enum)lookup.get(code.toString());
}
}
我的 BaseEnumDeserialiazer 是:
public class BaseEnumDeserializer<T extends Enum<T> & BaseEnum> extends StdDeserializer<T> {
public BaseEnumDeserializer() {
this((Class)null);
}
public BaseEnumDeserializer(Class<T> vc) {
super(vc);
}
public T deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException {
Field field = this.findField(jsonparser.getCurrentName(), jsonparser.getCurrentValue().getClass());
Class<T> javaType = field.getType();
return BaseEnum.fromCode(javaType, jsonparser.getText());
}
public Field findField(String name, Class<?> c) {
while(c != null) {
Field[] var3 = c.getDeclaredFields();
int var4 = var3.length;
for(int var5 = 0; var5 < var4; ++var5) {
Field field = var3[var5];
if (!Modifier.isStatic(field.getModifiers()) && field.getName().equals(name)) {
return field;
}
}
c = c.getSuperclass();
}
return null;
}
}
但最后它不會將"lang": ["en_US", "en_UK"]
轉換為EnmLanguage
List
。 我認為它不知道轉換為哪個BaseEnum
。 我應該如何讓它知道它應該將其轉換為List<EnmLanguage>
?
對於您的特定情況,在基本類型中添加 static @JsonCreator
方法可能就足夠了。
interface Lang {
@JsonCreator
static Lang valueOf(String value) {
return Languages.valueOf(value);
}
}
@JsonFormat(shape = JsonFormat.Shape.STRING)
enum Languages implements Lang {
en_US,
en_GB
}
然后您可以將其解析為任何其他 class
class LangTest {
private final ObjectMapper mapper = new ObjectMapper()
.setAnnotationIntrospector(new JacksonAnnotationIntrospector());
@Test
void readsJson() throws IOException {
final Lang[] tree = this.mapper
.readerFor(Lang[].class)
.readValue("[\"en_US\", \"en_GB\"]");
Assertions.assertArrayEquals(
tree,
new Lang[]{
Languages.en_US,
Languages.en_GB
}
);
}
}
這是一個簡單的BaseEnum
接口,
public interface BaseEnum {
Object getCode();
String getText();
}
這是實現BaseEnum
接口的EnmLanguage
,
public enum EnmLanguage implements BaseEnum {
en_US("en_US", "English"),
en_UK("en_UK", "English"),
tr_TR("tr_TR", "Turkish");
private String code;
private String text;
EnmLanguage(String code, String text) {
this.code = code;
this.text = text;
}
@Override
public String getCode() {
return code;
}
@Override
public String getText() {
return text;
}
}
這是另一個實現EnmElement
接口的BaseEnum
,
public enum EnmElement implements BaseEnum {
H("H", "Hydrogen"),
He("He", "Helium"),
Li("Li", "Lithium");
private String code;
private String text;
EnmElement(String code, String text) {
this.code = code;
this.text = text;
}
@Override
public String getCode() {
return code;
}
@Override
public String getText() {
return text;
}
}
這是一個簡單的單元測試,
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class EnumTest {
@Test
public void testDeserializeLanguage() throws IOException {
ObjectMapper mapper = new ObjectMapper();
EnmLanguage[] expected = {EnmLanguage.en_US, EnmLanguage.tr_TR};
EnmLanguage[] actual = mapper
.readerFor(EnmLanguage[].class)
.readValue(mapper.writeValueAsString(expected));
assertNotNull(actual);
assertArrayEquals(expected, actual);
}
@Test
public void testDeserializeElement() throws IOException {
ObjectMapper mapper = new ObjectMapper();
EnmElement[] expected = {EnmElement.H, EnmElement.He, EnmElement.Li};
EnmElement[] actual = mapper
.readerFor(EnmElement[].class)
.readValue(mapper.writeValueAsString(expected));
assertNotNull(actual);
assertArrayEquals(expected, actual);
}
}
使用枚舉的稍微復雜一點的例子,
import lombok.Data;
@Data
public class CompositeExample {
private String name;
private EnmLanguage[] lands;
private EnmElement[] elements;
}
一個示例單元測試片段,
@Test
public void testDeserialize() throws IOException {
CompositeExample expected = new CompositeExample();
String name = "Hello";
expected.setName(name);
EnmLanguage[] langs = {EnmLanguage.en_US, EnmLanguage.tr_TR};
expected.setLangs(langs);
EnmElement[] elements = {EnmElement.H, EnmElement.He, EnmElement.Li};
expected.setElements(elements);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(expected);
//{"name":"Hello","langs":["en_US","tr_TR"],"elements":["H","He","Li"]}
CompositeExample actual = mapper
.readerFor(CompositeExample.class)
.readValue(json);
assertNotNull(actual);
assertEquals(expected, actual);
}
嘗試使用toString()
啟用讀寫枚舉:
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.