Cách giải mã chuỗi JSON thành enum
Tôi có JSON trông giống như sau:
{
"name": "john",
"options": {
"test": 1,
"operation": "op1", // I need to deserialize this option to enum.
...
// any number of options
}
}
và tôi có lớp trông giống như sau:
public class Info {
public String name;
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public Map<String, Object> options;
}
public enum OperationEnum {OP1, OP2, OP3}
Làm cách nào tôi có thể deserialize để optionslập bản đồ operationnhư enumvà testtớiInteger
Trả lời
Bạn sẽ có thể sử dụng @JsonAnySetterđể trợ giúp bạn tại đây:
public class Info {
public static class Options {
public int test;
public OperationEnum operation;
}
public String name;
public Options options;
private final Map<String, Object> properties = new HashMap<>();
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
public enum OperationEnum {OP1, OP2, OP3}
Có một bài viết tốt ở đây: https://www.concretepage.com/jackson-api/jackson-jsonanygetter-and-jsonanysetter-example
Tại sao không làm như thế này:
public class Info {
public static class Options {
public int test;
public OperationEnum operation;
}
public String name;
public Options options;
}
public enum OperationEnum {OP1, OP2, OP3}
Sau đó, nó sẽ JustWork!
Cấu trúc JSON, nơi tất cả các tùy chọn (thuộc các loại khác nhau) được lưu trữ như Map<String, Object> options;thực thi phân tích cú pháp bổ sung, vì loại giá trị được xác định dựa trên nhãn (like "operation"và OperationEnumclass) Dưới đây là 2 cách tiếp cận với ObjectMapper.readValuevàEnum.valueOf
Nếu có thể, hãy xem xét các giải pháp linh hoạt hơn như từ @Matthew
class Demo {
public static void main(String[] args) throws Exception {
ObjectMapper om = new ObjectMapper();
Info info = om.readValue(jsonValue, Info.class);
OperationEnum operationM = om.readValue("\"" + info.options.get("operation") + "\"", OperationEnum.class);
System.out.println(operationM);
OperationEnum operationE = OperationEnum.valueOf(info.options.get("operation").toString());
System.out.println(operationE);
}
static String jsonValue = "{\n" +
" \"name\": \"john\",\n" +
" \"options\": {\n" +
" \"test\": 1,\n" +
" \"operation\": \"OP1\" \n" +
" }\n" +
"}";
}
Giải pháp đơn giản là bọc Mapcá thể bằng một lớp và triển khai các phương thức bổ sung cho mỗi thuộc tính không thông thường. Bạn có thể sử dụng @JsonAnySetterchú thích để lưu trữ tất cả các key-valuecặp.
Xem ví dụ dưới đây:
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
public class JsonOptionsWithCustomEnumApp {
public static void main(String[] args) throws IOException {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
Info info = mapper.readValue(jsonFile, Info.class);
Options options = info.getOptions();
System.out.println(options.toMap());
System.out.println(options.getOperation());
}
}
class Info {
private String name;
private Options options;
//getters, setters
}
class Options {
private Map<String, Object> values = new LinkedHashMap<>();
@JsonAnySetter
private void setValues(String key, Object value) {
values.put(key, value);
}
public OperationEnum getOperation() {
Object operation = values.get("operation");
if (operation == null) {
return null;
}
return Arrays.stream(OperationEnum.values())
.filter(op -> op.name().equalsIgnoreCase(operation.toString()))
.findFirst()
.orElse(null);
}
public Map<String, Object> toMap() {
return values;
}
}
enum OperationEnum {OP1, OP2, OP3}
Các bản in mã trên:
{test=1, operation=op1}
OP1