When reading a JSON file, i would like to map my class as follows:
在读取JSON文件时,我想映射我的类如下:
public class Effect {
private final String type;
private final Map<String, String> parameters;
public Effect(String type, Map<String, String> parameters) {
this.type = type;
this.parameters = parameters;
}
public String getType() {
return this.type;
}
public Map<String, String> getParameters() {
return this.parameters;
}
}
{
"type": {
"key1": "value1",
"key2": "value2",
}
}
So, the mapped JSON object consists of type
as the only key and parameters
as its value.
因此,映射的JSON对象由类型作为惟一的键,参数作为其值。
I would like to use @JsonCreator
on the constructor, but can't figure out, how to map the fields. Do i need to write a custom deserializer or is there an easier way to map the class like i want?
我想在构造函数中使用@JsonCreator,但不知道如何映射字段。我需要编写一个自定义反序列化器,还是有一种更简单的方法可以像我想要的那样映射类?
I wrote a custom deserializer, which does what i want, but there might be an easier way, maybe with annotations alone, which i would like to know:
我写了一个自定义反序列化器,它可以做我想做的事,但是可能有一种更简单的方法,也许只有注释,我想知道:
public class EffectDeserializer extends StdDeserializer<Effect> {
private static final long serialVersionUID = 1L;
public EffectDeserializer() {
super(Effect.class);
}
@Override
public Effect deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
JsonNode node = parser.getCodec().readTree(parser);
Iterator<String> fieldNames = node.fieldNames();
if(fieldNames.hasNext()) {
String type = fieldNames.next();
Map<String, String> parameters = new HashMap<>();
for(Iterator<Entry<String, JsonNode>> fields = node.get(type).fields(); fields.hasNext(); ) {
Entry<String, JsonNode> field = fields.next();
parameters.put(field.getKey(), field.getValue().textValue());
}
return new Effect(type, parameters);
}
return null;
}
}
Another way i found would be adding a JsonCreator
(constructor in this case), that takes a Map.Entry<String, Map<String, String>
and uses that to initialize the values, like this:
我发现的另一种方法是添加一个JsonCreator(本例中为构造函数),它具有一个映射。条目
@JsonCreator
public Effect(Map.Entry<String, Map<String, String>> entry) {
this.type = entry.getKey();
this.parameters = entry.getValue();
}
If there's no way to get it done with a "normal" constructor, i will probably end up using this, as it uses Jackson's default mapping for Map.Entry
, reducing possible error margin.
如果没有办法用“普通”构造函数来完成,我可能会使用这个,因为它使用Jackson的默认映射映射。进入,减少可能的误差幅度。
1 个解决方案
#1
1
Add a static factory method that accepts a Map
with a dynamic key:
添加一个静态工厂方法,该方法接受带有动态键的映射:
@JsonCreator
public static Effect create(Map<String, Map<String, String>> map) {
String type = map.keySet().iterator().next();
return new Effect(type, map.get(type));
}
EDIT: Just noticed this is basically an uglier version of your own solution using Map.Entry
. I would go with that instead.
编辑:注意到这基本上是一个更丑陋的版本,您自己的解决方案使用Map.Entry。我宁愿选择那个。
#1
1
Add a static factory method that accepts a Map
with a dynamic key:
添加一个静态工厂方法,该方法接受带有动态键的映射:
@JsonCreator
public static Effect create(Map<String, Map<String, String>> map) {
String type = map.keySet().iterator().next();
return new Effect(type, map.get(type));
}
EDIT: Just noticed this is basically an uglier version of your own solution using Map.Entry
. I would go with that instead.
编辑:注意到这基本上是一个更丑陋的版本,您自己的解决方案使用Map.Entry。我宁愿选择那个。