Deserialisieren der JSON-Zeichenfolge zum Aufzählen
Ich habe den JSON wie folgt aussehen:
{
"name": "john",
"options": {
"test": 1,
"operation": "op1", // I need to deserialize this option to enum.
...
// any number of options
}
}
und ich habe die Klasse sieht wie folgt aus:
public class Info {
public String name;
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public Map<String, Object> options;
}
public enum OperationEnum {OP1, OP2, OP3}
Wie kann ich deserialisieren, options
um operation
wie enum
und test
zu kartierenInteger
Antworten
Sie sollten in der Lage sein, @JsonAnySetter
Ihnen hier zu helfen:
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}
Hier gibt es eine gute Zusammenfassung: https://www.concretepage.com/jackson-api/jackson-jsonanygetter-and-jsonanysetter-example
Warum nicht so:
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}
Dann sollte es JustWork sein!
Die JSON-Struktur, in der alle Optionen (verschiedener Art) wie gespeichert werden, Map<String, Object> options;
erzwingt eine zusätzliche Analyse, da der Werttyp anhand der Bezeichnung (wie "operation"
und OperationEnum
Klasse) identifiziert wird. Hier sind zwei Ansätze mit ObjectMapper.readValue
undEnum.valueOf
Wenn es möglich ist, ziehen Sie flexiblere Lösungen wie die von @Matthew in Betracht
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" +
"}";
}
Eine einfache Lösung besteht darin, die Map
Instanz mit einer Klasse zu versehen und zusätzliche Methoden für jede nicht reguläre Eigenschaft zu implementieren. Sie können @JsonAnySetter
Anmerkungen verwenden, um alle key-value
Paare zu speichern .
Siehe Beispiel unten:
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}
Der obige Code druckt:
{test=1, operation=op1}
OP1