将JSON反序列化为现有对象(Java)

我想知道如何让Jackson JSON库将JSON反序列化为现有对象? 我试图找到如何做到这一点; 但它似乎只能采取一个类并自己实例化它。

或者,如果不可能,我想知道是否有任何Java JSON反序列化库可以做到这一点。

这似乎是C#的一个相应问题:将数据从JSON字符串覆盖到现有对象实例 。 看来JSON.NET有一个PopulateObject(字符串,对象)。

你可以用Jackson做到这一点:

mapper.readerForUpdating(object).readValue(json); 

另请参阅使用Jackson合并两个JSON文档

如果您可以使用其他库而不是jackson,您可以尝试Genson http://owlike.github.io/genson/ 。 除了一些其他不错的function(例如使用非空构造函数反序列化而没有任何注释,反序列化为多态类型等),它还支持将JavaBean反序列化为现有实例。 这是一个例子:

 BeanDescriptorProvider provider = new Genson().getBeanDescriptorFactory(); BeanDescriptor descriptor = provider.provide(MyClass.class, genson); ObjectReader reader = new JsonReader(jsonString); MyClass existingObject = descriptor.deserialize(existingObject, reader, new Context(genson)); 

如果您有任何疑问,请随时使用其邮件列表http://groups.google.com/group/genson 。

如果您使用的是spring框架,则可以使用BeanUtils库执行此任务。 首先正常反序列化您的json String,然后使用BeanUtils在父对象中设置此对象。 它还期望在父对象内设置对象的变量名称。 这是代码片段:

 childObject = gson.fromJson("your json string",class.forName(argType)) BeanUtils.setProperty(mainObject, "childObjectName", childObject); 

一种解决方案是解析新的对象图/树,然后统一复制到现有的对象图/树中。 但这当然效率较低,而且工作量更大,特别是如果具体类型不同,因为类型信息的可用性较低。 (所以不是一个真正的答案。我希望有更好的答案,只是想避免其他人以这种方式回答。)

flexJson也可以帮助你做同样的事情。

以下是从FlexJson Doc复制的示例

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().deserializeInto(json, charlieClone); 

请注意,p中返回的引用与charlieClone相同,只是更新了值。

我用Jackson + Spring的DataBinder来完成这样的事情。 此代码处理数组但不处理嵌套对象。

 private void bindJSONToObject(Object obj, String json) throws IOException, JsonProcessingException { MutablePropertyValues mpv = new MutablePropertyValues(); JsonNode rootNode = new ObjectMapper().readTree(json); for (Iterator> iter = rootNode.getFields(); iter.hasNext(); ) { Entry entry = iter.next(); String name = entry.getKey(); JsonNode node = entry.getValue(); if (node.isArray()) { List values = new ArrayList(); 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); } 

总是可以加载到虚拟对象并使用reflection来传输数据。 如果你的心脏刚刚使用gson

例。 假设此代码位于要将数据复制到的对象中

  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 tempFields = new ArrayList(); ArrayList ourFields = new ArrayList(); 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 getAllFields(List fields, Class type) { for (Field field : type.getDeclaredFields()) { fields.add(field); } if (type.getSuperclass() != null) { fields = getAllFields(fields, type.getSuperclass()); } return fields; }