2015-11-02 2 views
3

Я хочу изменить объект java, передав json String в мое приложение. Строка будет не содержит всю информацию о полном, измененном объекте, а просто один член, который должен быть установлен.Слияние объектов в объект java (JSON)

class SomeClass { 

    Object var1 = "Hello"; 
    Object var2 = "AAA"; 

    // A lot of fields goes here ... 

} 

public AppTest() throws Exception { 

    SomeClass myObject = new SomeClass(); 
    myObject.var2 = "BBB"; 

    String modification = "{\"var1\":\"Goodbye\"}"; 

    Gson gson = new Gson(); 
    SomeClass modifed = gson.fromJson(modification, SomeClass.class); 

    // TODO: Merge a modifed object into myObject somehow 

} 

Кроме того, некоторые из полей могут быть объектами с любым количеством полей. Опять же, я могу просто изменить один примитив внутри дочернего объекта. Более сложный пример:

class SomeOtherClass { 

    String var4 = "444"; 
    String var5 = "555"; 

} 

class SomeClass { 

    Object var1 = "111"; 
    Object var2 = "222"; 
    SomeOtherClass var3 = new SomeOtherClass(); 

} 

public AppTest() throws Exception { 

    SomeClass myObject = new SomeClass(); 
    myObject.var2 = "AAA"; 
    myObject.var3.var5 = "BBB"; 

    String modification = "{\"var3\":{\"var5\":\"XXX\"}}"; 

    Gson gson = new Gson(); 
    SomeClass modifed = gson.fromJson(modification, SomeClass.class); 

    // TODO: Merge the modifed object into myObject somehow 

} 

Итак, вопрос в том, как частично изменить объект с помощью JSON?

ответ

1

Удалось создать рекурсивный метод для замены свойств в JsonObject.

private static void mergeObjects(JsonObject object, JsonObject modification) { 

    // Iterate through the modified properties 
    for (Entry<String, JsonElement> entry : modification.entrySet()) { 

     JsonElement je = entry.getValue(); 

     // If the modified property is an object, iterate through the properties of the modified property 
     if (je instanceof JsonObject) { 

      JsonObject nextOrigObject = object.get(entry.getKey()).getAsJsonObject(); 
      JsonObject nextModObject = je.getAsJsonObject(); 

      mergeObjects(nextOrigObject, nextModObject); 

     } 

     // If the modified property is not an object, set the original object to match the modified property 
     else 
      object.add(entry.getKey(), je); 

    } 

} 

С помощью этого метода, я могу объединить два объекта следующим образом:

class SomeClass { 

    Object var1 = "Hello"; 
    Object var2 = "AAA"; 

} 

public TestApplication() { 

    SomeClass myObject = new SomeClass(); 
    myObject.var2 = "BBB"; 

    String modificationString = "{\"var1\":\"Goodbye\"}"; 

    Gson gson = new Gson(); 
    JsonObject original = gson.fromJson(gson.toJson(myObject), JsonObject.class); 
    JsonObject modification = gson.fromJson(modificationString, JsonObject.class); 


    mergeObjects(original, modification); 
    myObject = gson.fromJson(original, SomeClass.class); 

    System.out.println(myObject.var1); // Prints "Goodbye" 

} 

public static void main(String[] args) { 
    new DummyFile(); 
} 

Комментарии?

Могут быть более красивые способы конвертировать объект SomeClass в JsonObject перед слиянием, не стесняйтесь добавлять свои предложения.

EDIT: добавлено еще в слиянии методу

edit2: добавлены комментарии

-1

Любая проблема в выполнении этой

modifed.var2=myObject.var2; 
    String modificationStr = gson.toJson(modifed); 
    System.out.println(modificationStr); 
+0

Вы предлагаете мне сделать это для каждого и каждой переменной из моих объектов? «myObject» в примере (последний) имеет 4 примитива json, мое приложение может иметь сотни ... И как определить, какая переменная «модифицированный» объект должна модифицировать? – gromit190

+0

Я имел в виду: * каждая переменная моих классов – gromit190

1

Привет Я попробовал один псевдо образец, как показано ниже:

static Object merge(Object target, Object modified) { 

     for (Field f : target.getClass().getDeclaredFields()) { 
      if (!f.isAccessible()) { 
       f.setAccessible(true); 
      } 
      if (f.getType().isPrimitive()) { 

        try { 
         if (f.getType().isAssignableFrom(java.lang.Boolean.TYPE) 
           && f.getBoolean(modified) != f.getBoolean(target)) { 
          f.setBoolean(target, f.getBoolean(modified)); 
         } else if (f.getType().isAssignableFrom(java.lang.Character.TYPE) 
           && f.getChar(modified) != f.getChar(target)) { 
          f.setChar(target, f.getChar(modified)); 
         } else if (f.getType().isAssignableFrom(java.lang.Integer.TYPE) 
           && f.getInt(modified) != f.getInt(target)) { 
          f.setInt(target, f.getInt(modified)); 
         } 
         //.... 
         // do it for all other primitive types 
         //also consider Enum types(not primitive so check 'f.getType().isEnum()') 
        } catch (IllegalArgumentException e) { 
         e.printStackTrace(); 
        } catch (IllegalAccessException e) { 
         e.printStackTrace(); 
        } 


      } else if (f.getType().getPackage().getName().matches("java.lang.*") 
        || f.getType().getPackage().getName().matches("java.util.*")) { 
       /* Here I am trying to directly assign changes for the basic packages, if you want more you can add more packages*/ 

       try { 
        if (f.get(modified) != null && f.get(target) != f.get(modified)) { 
         f.set(target, f.get(modified)); 
        } 
       } catch (IllegalAccessException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       /* If local classes encountered as member variables then do the same merge!*/ 
       try { 
        merge(f.get(target), f.get(modified)); 
       } catch (IllegalArgumentException e) { 
        e.printStackTrace(); 
       } catch (IllegalAccessException e) { 
        e.printStackTrace(); 
       } 
      } 

     } 
     return target; 

    } 

вы можете вызвать этот метод как myObject = (SomeClass) merge(myObject, modifed);

Примечание: Это не полностью функциональный метод для выполнения вашей работы, пожалуйста, прочитайте комментарии в строке и сделайте это идеально подходящим для вашего дела. Я только гарантирую базовую функциональность

+0

Действительно оценить усилия, мне удалось создать метод для объединения JsonObjects. Он работает, поэтому я думаю, что поеду с ним. – gromit190

+1

Хорошо, могут быть другие хорошие способы, как вы сказали. вы можете поделиться своей реализацией, если она сработает. Будет полезно для других. –

+0

Добавлен ответ, сообщите мне, если вы думаете, что я лучше поеду с вашим методом. – gromit190

Смежные вопросы