Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将JSON字符串反序列化到枚举_Java_Jackson_Jackson Databind - Fatal编程技术网

Java 如何将JSON字符串反序列化到枚举

Java 如何将JSON字符串反序列化到枚举,java,jackson,jackson-databind,Java,Jackson,Jackson Databind,我的JSON如下所示: { "name": "john", "options": { "test": 1, "operation": "op1", // I need to deserialize this option to enum. ... // any number of options } } public cla

我的JSON如下所示:

{
  "name": "john",
  "options": {
    "test": 1,
    "operation": "op1",     // I need to deserialize this option to enum.
    ...
    // any number of options
  }
}
public class Info {
    public String name;
    @JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
    public Map<String, Object> options;
}

public enum OperationEnum {OP1, OP2, OP3}
我的课程如下所示:

{
  "name": "john",
  "options": {
    "test": 1,
    "operation": "op1",     // I need to deserialize this option to enum.
    ...
    // any number of options
  }
}
public class Info {
    public String name;
    @JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
    public Map<String, Object> options;
}

public enum OperationEnum {OP1, OP2, OP3}
公共类信息{
公共字符串名称;
@JsonTypeInfo(use=JsonTypeInfo.Id.NONE)
公共地图选项;
}
公共枚举操作数{OP1,OP2,OP3}

如何反序列化到
选项
映射
操作
枚举
测试
整数
为什么不这样做:


公共类信息{
公共静态类选项{
公共智力测验;
公共操作数操作;
}
公共字符串名称;
公共选择;
}
公共枚举操作数{OP1,OP2,OP3}

那它就应该起作用了

JSON结构,其中所有选项(不同类型)都像
Map选项一样存储
强制执行额外的解析,因为值类型是基于标签标识的(如
“operation”
OperationEnum
类) 以下是使用
ObjectMapper.readValue
Enum.valueOf

如果可能的话,考虑更灵活的解决方案,比如@马修

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" +
            "}";
}

您应该能够使用
@JsonAnySetter
来帮助您:

公共类信息{
公共静态类选项{
公共智力测验;
公共操作数操作;
}
公共字符串名称;
公共选择;
私有最终映射属性=new HashMap();
@JSONANYSETER
公共void添加(字符串键、字符串值){
属性。put(键、值);
}
}
公共枚举操作数{OP1,OP2,OP3}

这里有一个很好的说明:

简单的解决方案是用类包装
Map
实例,并为每个非常规属性实现额外的方法。您可以使用
@JsonAnySetter
注释来存储所有
键值对

请参见以下示例:

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}

为什么使用map而不是DTO类呢?
Info
类是DTO。我在里面使用一个映射,因为我可以得到任意数量的选项。你可以为你的
Info
类使用一个自定义反序列化程序,然后检查选项映射中的数据,看看是否有
operationnum
。对于每个选项,您可以使用
operationnum.valueOf
我不能这样做,因为我需要一个选项映射。我可以得到任意数量的参数,我需要处理它。我明白了。我不确定是否有一个好的解决方案-请参见此处:但在
readValue
之后,我想做如下操作:
(operationnum)info.options.get(“operation”)
我确信它会起作用,您尝试过吗?因为Jackson将如何将OP1绑定到enum
operationnum
?@Maelig:是的,它可以工作,需要一些额外的解析