将 JSON 反序列化为现有对象 (Java)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12518618/
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
Deserialize JSON into existing object (Java)
提问by Jonas N
I'd like to know how one might get the Hymanson JSON library to deserialize JSON into an existing object? I've tried to find how to to this; but it seems to only be able to take a Class and instantiate it itself.
我想知道如何让 Hymanson JSON 库将 JSON 反序列化为现有对象?我试图找到如何做到这一点;但它似乎只能接受一个类并实例化它本身。
Or if not possible, I'd like to know if any Java JSON deserialization libraries can do it.
或者,如果不可能,我想知道是否有任何 Java JSON 反序列化库可以做到。
This seems to be a corresponding question for C#: Overlay data from JSON string to existing object instance. It seems JSON.NET has a PopulateObject(string,object).
这似乎是 C# 的相应问题:Overlay data from JSON string to existing object instance。JSON.NET 似乎有一个 PopulateObject(string,object)。
回答by Johan Boberg
You can do this using Hymanson:
您可以使用 Hymanson 执行此操作:
mapper.readerForUpdating(object).readValue(json);
回答by eugen
If you can use another library instead of Hymanson you can try Genson http://owlike.github.io/genson/. In addition of some other nice features (such as deserialize using a non empty constructor without any annotation, deserialize to polymorphic types, etc) it supports deserialization of JavaBean into an existing instance. Here is an example:
如果您可以使用另一个库而不是 Hymanson,您可以尝试 Genson http://owlike.github.io/genson/。除了一些其他不错的功能(例如使用没有任何注释的非空构造函数反序列化,反序列化为多态类型等)之外,它还支持将 JavaBean 反序列化为现有实例。下面是一个例子:
BeanDescriptorProvider provider = new Genson().getBeanDescriptorFactory();
BeanDescriptor<MyClass> descriptor = provider.provide(MyClass.class, genson);
ObjectReader reader = new JsonReader(jsonString);
MyClass existingObject = descriptor.deserialize(existingObject, reader, new Context(genson));
If you have any question don't hesitate to use its mailing list http://groups.google.com/group/genson.
如果您有任何问题,请随时使用其邮件列表http://groups.google.com/group/genson。
回答by yokesh sharma
If you are using spring framework you can use BeanUtils library for this task. First deserialize your json String normally and then use BeanUtils to set this object inside a parent object. It also expects the variable name of the object to be set inside the parent object. Here is the code snippet:
如果您使用的是 spring 框架,则可以将 BeanUtils 库用于此任务。首先正常反序列化您的 json 字符串,然后使用 BeanUtils 在父对象中设置此对象。它还期望在父对象内设置对象的变量名称。这是代码片段:
childObject = gson.fromJson("your json string",class.forName(argType))
BeanUtils.setProperty(mainObject, "childObjectName", childObject);
回答by LSafer SE
You can use my repositories :).
您可以使用我的存储库:)。
Object yo = //yourObject
String js = //json source
Map remote = Object$.remoteMap(yo, false); //or you can use Bean.forInstance(yo);
Reader reader = new StringReader(js);//you can replace this with any reader :)
AtomicReference buffer = new AtomicReference(remote);
try {
JSON.global.parse(buffer, reader, null, null);
} catch (IOException ignored) {
//If any exception got thrown by the reader
}
this way, JSON will parse values to the map it finds in the buffer. And if the map contains a list and the JSON value also has a list. The list on the map will not be replaced. instead, it will be used to contain the values.
这样,JSON 会将值解析为它在缓冲区中找到的映射。如果地图包含一个列表并且 JSON 值也有一个列表。地图上的列表不会被替换。相反,它将用于包含值。
If you used Bean.forInstance(yo)
the returned remote map will have some additional features.
如果您使用Bean.forInstance(yo)
返回的远程地图将有一些附加功能。
repositories:
存储库:
util repo (required): github.com/cufyorg/util
util repo(必需): github.com/cufyorg/util
base repo (required): github.com/cufyorg/base
基本回购(必需): github.com/cufyorg/base
JSON repo (required): github.com/cufyorg/json
JSON 存储库(必需): github.com/cufyorg/json
beans repo (optional): github.com/cufyorg/beans
豆类回购(可选): github.com/cufyorg/beans
回答by Jordan Haynes
could always load into a dummy object and use reflection to transfer the data. if your heart is set on just using gson
总是可以加载到一个虚拟对象中并使用反射来传输数据。如果您只使用 gson
example. assuming this code is in the object you want to copy data into
例子。假设此代码位于您要将数据复制到的对象中
public void loadObject(){
Gson gson = new Gson();
//make temp object
YourObject tempStorage = (YourObject) gson.fromJson(new FileReader(theJsonFile), YourObject.class);
//get the fields for that class
ArrayList<Field> tempFields = new ArrayList<Field>();
ArrayList<Field> ourFields = new ArrayList<Field>();
getAllFields(tempFields, tempStorage.getClass());
getAllFields(thisObjectsFields, this.getClass());
for(Field f1 : tempFields){
for(Field f2 : thisObjectsFields){
//find matching fields
if(f1.getName().equals(f2.getName()) && f1.getType().equals(f2.getType())){
//transient and statics dont get serialized and deserialized.
if(!Modifier.isTransient(f1.getModifiers())&&!Modifier.isStatic(f1.getModifiers())){
//make sure its a loadable thing
f2.set(this, f1.get(tempStorage));
}
}
}
}
}
}
public static List<Field> getAllFields(List<Field> fields, Class<?> type) {
for (Field field : type.getDeclaredFields()) {
fields.add(field);
}
if (type.getSuperclass() != null) {
fields = getAllFields(fields, type.getSuperclass());
}
return fields;
}
回答by faizan
flexJson can also help you do the same.
flexJson 也可以帮助你做同样的事情。
Here is an example copied from FlexJson Doc
这是从FlexJson Doc复制的示例
The deserializeInto function takes your string and reference to existing object.
deserializeInto 函数接受您的字符串和对现有对象的引用。
Person charlie = new Person("Charlie", "Hubbard", cal.getTime(), home, work );
Person charlieClone = new Person( "Chauncy", "Beauregard", null, null, null );
Phone fakePhone = new Phone( PhoneNumberType.MOBILE, "303 555 1234");
charlieClone.getPhones().add( fakePhone );
String json = new JSONSerializer().include("hobbies").exclude("firstname", "lastname").serialize( charlie );
Person p = new JSONDeserializer<Person>().deserializeInto(json, charlieClone);
Note that the reference returned in p is same as charlieClone just with updated values.
请注意, p 中返回的引用与 charlieClone 相同,只是具有更新的值。
回答by splashout
I used Hymanson + Spring's DataBinder to accomplish something like this. This code handles arrays but not nested objects.
我使用 Hymanson + Spring 的 DataBinder 来完成这样的事情。此代码处理数组但不处理嵌套对象。
private void bindJSONToObject(Object obj, String json) throws IOException, JsonProcessingException {
MutablePropertyValues mpv = new MutablePropertyValues();
JsonNode rootNode = new ObjectMapper().readTree(json);
for (Iterator<Entry<String, JsonNode>> iter = rootNode.getFields(); iter.hasNext(); ) {
Entry<String, JsonNode> entry = iter.next();
String name = entry.getKey();
JsonNode node = entry.getValue();
if (node.isArray()) {
List<String> values = new ArrayList<String>();
for (JsonNode elem : node) {
values.add(elem.getTextValue());
}
mpv.addPropertyValue(name, values);
if (logger.isDebugEnabled()) {
logger.debug(name + "=" + ArrayUtils.toString(values));
}
}
else {
mpv.addPropertyValue(name, node.getTextValue());
if (logger.isDebugEnabled()) {
logger.debug(name + "=" + node.getTextValue());
}
}
}
DataBinder dataBinder = new DataBinder(obj);
dataBinder.bind(mpv);
}
回答by Jonas N
One solution is to parse a new object graph/tree and then unify-copy into the existing object graph/tree. But that's of course less efficient, and more work, especially if concrete types differ because of less availability of type information. (So not really an answer. I hope there's a better answer, just want to avoid others answering in this way.)
一种解决方案是解析一个新的对象图/树,然后统一复制到现有的对象图/树中。但这当然效率较低,而且工作量更大,尤其是当具体类型因类型信息的可用性较低而不同时。(所以不是真正的答案。我希望有更好的答案,只是想避免其他人以这种方式回答。)