我有一个简单的包装类。
class Wrapper {
int id;
Object command;
}
command
可能是我从外部获取的对象,我无法创建一个接口来将可能的类型保存在一起。
我想简单地序列化它:
String json = objectMapper.writeValueAsString(wrapper);
所以我得到了:
{"id":"1","command":{"type" : "objectType", "key0": "val0", ... other properties...}}
理想情况下,我会使用type
的可能值和相应的类名作为值构建一个注册表,因此我可以像这样反序列化它:
Wrapper wrapper = objectMapper.readValue(bytes, Wrapper.class);
(objectMapper
是com.fasterxml.jackson.databind.ObjectMapper
)
有没有办法通过Jackson
来实现这一目标?
答案 0 :(得分:1)
您可以使用the Jackson polymorphic type handling。您可以使用@JsonTypeXXX
注释声明命令属性可以使用哪种类型。
这是一个完整的例子:
public class JacksonTypeInfoOnObject {
public static class Bean {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(Command1.class),
@JsonSubTypes.Type(Command2.class)
})
public final Object command;
@JsonCreator
public Bean(@JsonProperty("command") final Object command) {this.command = command;}
@Override
public String toString() {
return "Bean{" +
"command=" + command +
'}';
}
}
@JsonTypeName("cmd1")
public static class Command1 {
@Override
public String toString() {
return "Command1{}";
}
}
@JsonTypeName("cmd2")
public static class Command2 {
@Override
public String toString() {
return "Command2{}";
}
}
public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
final List<Bean> list = Arrays.asList(
new Bean(new Command1()),
new Bean(new Command2()));
final String json = mapper.writeValueAsString(list);
System.out.println(json);
final List<Bean> values = mapper.readValue(json, new TypeReference<List<Bean>>() {});
System.out.println(values);
}
}
输出:
[{"command":{"type":"cmd1"}},{"command":{"type":"cmd2"}}]
[Bean{command=Command1{}}, Bean{command=Command2{}}]
答案 1 :(得分:0)
我将command
属性的类型更改为Map<String, Object>
,并且可以按预期序列化/反序列化Wrapper
对象。
下面是Main
类生成的输出:
SERIALIZE: {"id":1,"command":{"key0":"val0","type":"objectType"}}
DESERIALIZE: Wrapper [id=1, command={key0=val0, type=objectType}]
package json;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
static ObjectMapper objectMapper = new ObjectMapper();
private static Wrapper createWrapper() {
Wrapper wrapper = new Wrapper();
Map<String, Object> command = new HashMap<String, Object>();
command.put("type", "objectType");
command.put("key0", "val0");
wrapper.id = 1;
wrapper.command = command;
return wrapper;
}
private static String serializeWrapper(Wrapper wrapperObj) {
try {
return objectMapper.writeValueAsString(wrapperObj);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
private static Wrapper deserializeWrapper(String wrapperJsonStr) {
try {
return objectMapper.readValue(wrapperJsonStr, Wrapper.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Wrapper wrapper = createWrapper();
String wrapperJsonStr = serializeWrapper(wrapper);
System.out.printf("SERIALIZE: %s%n", wrapperJsonStr);
Wrapper wrapperObj = deserializeWrapper(wrapperJsonStr);
System.out.printf("DESERIALIZE: %s%n", wrapperObj);
}
}
package json;
import java.util.Map;
public class Wrapper {
public int id;
public Map<String, Object> command;
@Override
public String toString() {
return "Wrapper [id=" + id + ", command=" + command + "]";
}
}