如何使用 Java 和 Jackson 库对 Json 字符串进行多态反序列化?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6542833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I polymorphic deserialization Json String using Java and Hymanson Library?
提问by mohamede1945
I've some classes A, B, C they all inherit from class BaseClass.
我有一些类 A、B、C,它们都继承自 BaseClass 类。
I've a String json that contains the json representation of the A, B, C or BaseClass.
我有一个字符串 json,其中包含 A、B、C 或 BaseClass 的 json 表示。
I want to have some way to deserialize this String to the BaseClass (polymorphic deserialization). Something like this
我想有一些方法将此字符串反序列化为 BaseClass(多态反序列化)。像这样的东西
BaseClass base = ObjectMapper.readValue(jsonString, BaseClass.class);
jsonString
could be Json String representation of any of A, B, C, or BaseClass.
jsonString
可以是 A、B、C 或 BaseClass 中任何一个的 Json 字符串表示。
采纳答案by Programmer Bruce
It's not clear what problem the original poster is having. I'm guessing that it's one of two things:
目前尚不清楚原始海报有什么问题。我猜这是两件事之一:
Deserialization problems with unbound JSON elements, because the JSON contains elements for which there is nothing in the Java to bind to; or
Want to implement polymorphic deserialization.
未绑定 JSON 元素的反序列化问题,因为 JSON 包含 Java 中没有任何内容可绑定的元素;或者
想实现多态反序列化。
Here's a solution to the first problem.
这是第一个问题的解决方案。
import static org.codehaus.Hymanson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES;
import org.codehaus.Hymanson.map.ObjectMapper;
public class Foo
{
public static void main(String[] args) throws Exception
{
BaseClass base = new BaseClass();
A a = new A();
B b = new B();
C c = new C();
ObjectMapper mapper = new ObjectMapper();
String baseJson = mapper.writeValueAsString(base);
System.out.println(baseJson); // {"baseName":"base name"}
String aJson = mapper.writeValueAsString(a);
System.out.println(aJson); // {"baseName":"base name","aName":"a name"}
String bJson = mapper.writeValueAsString(b);
System.out.println(bJson); // {"baseName":"base name","bName":"b name"}
String cJson = mapper.writeValueAsString(c);
System.out.println(cJson); // {"baseName":"base name","cName":"c name"}
BaseClass baseCopy = mapper.readValue(baseJson, BaseClass.class);
System.out.println(baseCopy); // baseName: base name
// BaseClass aCopy = mapper.readValue(aJson, BaseClass.class);
// throws UnrecognizedPropertyException:
// Unrecognized field "aName", not marked as ignorable
// because the JSON contains elements for which no Java field
// to bind to was provided.
// Need to let Hymanson know that not all JSON elements must be bound.
// To resolve this, the class can be annotated with
// @JsonIgnoreProperties(ignoreUnknown=true) or the ObjectMapper can be
// directly configured to not FAIL_ON_UNKNOWN_PROPERTIES
mapper = new ObjectMapper();
mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
BaseClass aCopy = mapper.readValue(aJson, BaseClass.class);
System.out.println(aCopy); // baseName: base name
BaseClass bCopy = mapper.readValue(bJson, BaseClass.class);
System.out.println(bCopy); // baseName: base name
BaseClass cCopy = mapper.readValue(cJson, BaseClass.class);
System.out.println(cCopy); // baseName: base name
}
}
class BaseClass
{
public String baseName = "base name";
@Override public String toString() {return "baseName: " + baseName;}
}
class A extends BaseClass
{
public String aName = "a name";
@Override public String toString() {return super.toString() + ", aName: " + aName;}
}
class B extends BaseClass
{
public String bName = "b name";
@Override public String toString() {return super.toString() + ", bName: " + bName;}
}
class C extends BaseClass
{
public String cName = "c name";
@Override public String toString() {return super.toString() + ", cName: " + cName;}
}
Here's a solution to the second problem.
这是第二个问题的解决方案。
import org.codehaus.Hymanson.annotate.JsonSubTypes;
import org.codehaus.Hymanson.annotate.JsonSubTypes.Type;
import org.codehaus.Hymanson.annotate.JsonTypeInfo;
import org.codehaus.Hymanson.map.ObjectMapper;
public class Foo
{
public static void main(String[] args) throws Exception
{
BaseClass base = new BaseClass();
A a = new A();
B b = new B();
C c = new C();
ObjectMapper mapper = new ObjectMapper();
String baseJson = mapper.writeValueAsString(base);
System.out.println(baseJson); // {"type":"BaseClass","baseName":"base name"}
String aJson = mapper.writeValueAsString(a);
System.out.println(aJson); // {"type":"a","baseName":"base name","aName":"a name"}
String bJson = mapper.writeValueAsString(b);
System.out.println(bJson); // {"type":"b","baseName":"base name","bName":"b name"}
String cJson = mapper.writeValueAsString(c);
System.out.println(cJson); // {"type":"c","baseName":"base name","cName":"c name"}
BaseClass baseCopy = mapper.readValue(baseJson, BaseClass.class);
System.out.println(baseCopy); // baseName: base name
BaseClass aCopy = mapper.readValue(aJson, BaseClass.class);
System.out.println(aCopy); // baseName: base name, aName: a name
BaseClass bCopy = mapper.readValue(bJson, BaseClass.class);
System.out.println(bCopy); // baseName: base name, bName: b name
BaseClass cCopy = mapper.readValue(cJson, BaseClass.class);
System.out.println(cCopy); // baseName: base name, cName: c name
}
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@Type(value = A.class, name = "a"),
@Type(value = B.class, name = "b"),
@Type(value = C.class, name = "c") })
class BaseClass
{
public String baseName = "base name";
@Override public String toString() {return "baseName: " + baseName;}
}
class A extends BaseClass
{
public String aName = "a name";
@Override public String toString() {return super.toString() + ", aName: " + aName;}
}
class B extends BaseClass
{
public String bName = "b name";
@Override public String toString() {return super.toString() + ", bName: " + bName;}
}
class C extends BaseClass
{
public String cName = "c name";
@Override public String toString() {return super.toString() + ", cName: " + cName;}
}
If instead, the goal is to deserialize to a subclass type without a JSON element specifically dedicated to indicate what the subclass type is, then that is also possible, so long as something in the JSON can be used to decide what the subclass type should be. I posted an example of this approach at http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-Hymanson-into.html.
如果相反,目标是反序列化为子类类型,而没有专门用于指示子类类型的 JSON 元素,那么这也是可能的,只要 JSON 中的某些内容可用于决定子类类型应该是什么. 我在http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-Hymanson-into.html 上发布了一个这种方法的例子。
回答by theleftfielder
Have you looked at Google's Gson library? I think it does what you're looking for.
你看过谷歌的 Gson 库吗?我认为它可以满足您的需求。