Ответ 1
Вы можете сделать это, используя Джексон:
mapper.readerForUpdating(object).readValue(json);
См. также Объединение двух документов JSON с использованием Джексона
Я хотел бы знать, как можно получить библиотеку Jackson JSON для десериализации JSON в существующий объект? Я пытался найти, как к этому; но, похоже, он может взять только класс и создать его.
Или, если это невозможно, я хотел бы знать, могут ли какие-либо библиотеки десериализации Java JSON это сделать.
Это похоже на соответствующий вопрос для С#: Наложение данных из строки JSON в существующий экземпляр объекта. Кажется, у JSON.NET есть PopulateObject (строка, объект).
Вы можете сделать это, используя Джексон:
mapper.readerForUpdating(object).readValue(json);
См. также Объединение двух документов JSON с использованием Джексона
Если вы можете использовать другую библиотеку вместо Jackson, вы можете попробовать 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));
Если у вас есть какие-либо вопросы, не стесняйтесь использовать свой список рассылки http://groups.google.com/group/genson.
Если вы используете фреймворк spring, вы можете использовать библиотеку BeanUtils для этой задачи. Сначала десериализуйте свою строку json, а затем используйте 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<Person>().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<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);
}
всегда может загружаться в фиктивный объект и использовать отражение для передачи данных. если ваше сердце установлено только с помощью 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 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;
}