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

将JSON反序列化为现有对象(Java),java,json,jackson,deserialization,Java,Json,Jackson,Deserialization,我想知道如何让Jackson JSON库将JSON反序列化到现有对象中?我试着找到如何解决这个问题;但它似乎只能获取一个类并自己实例化它 或者,如果不可能,我想知道是否有Java JSON反序列化库可以做到这一点 这似乎是C#:的对应问题。似乎JSON.NET有一个PopulateObject(字符串,对象) 一种解决方案是解析新的对象图/树,然后将副本统一到现有的对象图/树中。但这当然会降低效率,增加工作量,特别是当具体类型因类型信息的可用性较低而有所不同时。(所以不是真正的答案。我希望有更好

我想知道如何让Jackson JSON库将JSON反序列化到现有对象中?我试着找到如何解决这个问题;但它似乎只能获取一个类并自己实例化它

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


这似乎是C#:的对应问题。似乎JSON.NET有一个PopulateObject(字符串,对象)

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

如果你可以使用另一个库而不是Jackson,你可以试试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));
BeanDescriptorProvider=new Genson().getBeanDescriptorFactory();
BeanDescriptor descriptor=provider.provide(MyClass.class,genson);
ObjectReader=新的JsonReader(jsonString);
MyClass existingObject=描述符。反序列化(existingObject、reader、新上下文(genson));

如果您有任何问题,请毫不犹豫地使用它的邮件列表。

flexJson也可以帮助您这样做

下面是从中复制的一个示例

反序列化为函数获取字符串和对现有对象的引用

 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);
Person charlie=新人(“charlie”,“Hubbard”,cal.getTime(),家,工作);
Person charletchlone=新人(“Chauncy”,“Beaurerd”,null,null,null);
Phone fakePhone=新手机(PhoneNumberType.MOBILE,“303 555 1234”);
charkephone.getPhones().add(fakePhone);
String json=new JSONSerializer().include(“嗜好”).exclude(“firstname”、“lastname”).serialize(charlie);
Person p=new JSONDeserializer().deserializeInto(json,charlone);

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

我使用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<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);
}
private void bindJSONToObject(Object obj,String json)抛出IOException,JsonProcessingException{
MutablePropertyValues mpv=新的MutablePropertyValues();
JsonNode rootNode=newObjectMapper().readTree(json);
for(迭代器iter=rootNode.getFields();iter.hasNext();){
Entry=iter.next();
字符串名称=entry.getKey();
JsonNode=entry.getValue();
if(node.isArray()){
列表值=新的ArrayList();
for(JsonNode元素:node){
add(elem.getTextValue());
}
mpv.addPropertyValue(名称、值);
if(logger.isDebugEnabled()){
logger.debug(名称+“=”+ArrayUtils.toString(值));
}
}
否则{
addPropertyValue(name,node.getTextValue());
if(logger.isDebugEnabled()){
logger.debug(name+“=”+node.getTextValue());
}
} 
}
DataBinder DataBinder=新的DataBinder(obj);
数据绑定(mpv);
}

您可以使用Jackson执行此操作:

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

另请参见

始终可以加载到虚拟对象中,并使用反射来传输数据。如果你一心只想使用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<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 void loadObject(){
Gson Gson=新的Gson();
//生成临时对象
YourObject tempStorage=(YourObject)gson.fromJson(新文件读取器(theJsonFile),YourObject.class);
//获取该类的字段
ArrayList tempFields=新的ArrayList();
ArrayList ourFields=新的ArrayList();
getAllFields(tempFields,tempStorage.getClass());
getAllFields(thisObjectsFields,this.getClass());
用于(字段f1:临时字段){
用于(字段f2:thisObjectsFields){
//查找匹配字段
if(f1.getName().equals(f2.getName())和&f1.getType().equals(f2.getType())){
//瞬态和静态不会被序列化和反序列化。
如果(!Modifier.isTransient(f1.getModifiers())和&!Modifier.isStatic(f1.getModifiers()){
//确保它是可装载的东西
f2.设置(此,f1.获取(临时存储));
}
}
}
}
}

公共静态列表getAllFields(列表字段,类类型){
for(字段:type.getDeclaredFields()){
字段。添加(字段);
}
if(type.getSuperclass()!=null){
fields=getAllFields(字段,类型.getSuperclass());
}
返回字段;
}

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

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

您可以使用我的存储库:)

这样,JSON将把值解析为它在缓冲区中找到的映射。如果映射包含一个列表,那么JSON值也有一个列表。地图上的列表将不会被替换。相反,它将用于包含值

如果您使用
Bean.example(yo)
返回的远程地图将具有一些附加功能

存储库:

util回购(必需):

基本回购(必需):

JSON回购协议(必需):


beans回购(可选):

您看过Gson吗?只是粗略的。它能做到上述吗?似乎不行,在…上有一个Gson问题“问题431:填充现有对象”,而“Gson路线图”只有“计划版本:Gson 2.2.3:”和空白空间
childObject = gson.fromJson("your json string",class.forName(argType))
BeanUtils.setProperty(mainObject, "childObjectName", childObject);
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
}