2015-12-04 2 views
1

Зачастую мне нужно объединить два объекта JSON (аналогично тому, как работает jQuery $.extend()). Однако библиотека Gson не имеет встроенных функций, и они сказали they won't implement it.Слияние/расширение объектов JSON с использованием Gson в Java

Делать что-то вроде:

private void merge(JsonObject firstObj, JsonObject secondObj){ 
    for(String keyInSecondObj : secondObj.entrySet().keySet()) { 
     if(!firstObj.has(keyInSecondObj)){ 
     firstObj.add(secondMap.get(keyInSecondObj)); 
    } 
} 

слишком просто потому, что она не работает рекурсивно сливающиеся JsonObjects, не обрабатывают конфликты, когда ключ существует в обеих картах, и не имеет никакой специальной обработки для непримитивного такие как массивы.

Мне не удалось найти готовые решения для этого. Я предпочел бы использовать что-то, что было тщательно протестировано вместо того, чтобы писать мой собственный метод, но он должен быть Gson (не Джексон или другой).

Изменить: Я в конечном итоге писать свою собственную реализацию, как добавили в качестве answer to this question

This question является не дубликат, потому что он не использует Gson (или Java по этому вопросу).

+1

Это simlar, но не использует библиотеку Gson: http://stackoverflow.com/questions/21160337/how-can-i-merge-two-jobject – bradvido

+0

Пожалуйста, ознакомьтесь с ними, прежде чем добавить теги их на ваш вопрос ... – Sumurai8

+1

@JarrodRoberson Этот вопрос не обман! Пожалуйста, см. Мое объяснение. В отмеченном дубликате даже не используется Java – bradvido

ответ

5

Вот моя первая попытка написать мой собственный метод статического слияния. Не стесняйтесь совать в нем дыры.

import com.google.gson.JsonArray; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonObject; 
import java.util.Map; 

public class GsonTools { 

    public static enum ConflictStrategy { 

     THROW_EXCEPTION, PREFER_FIRST_OBJ, PREFER_SECOND_OBJ, PREFER_NON_NULL; 
    } 

    public static class JsonObjectExtensionConflictException extends Exception { 

     public JsonObjectExtensionConflictException(String message) { 
      super(message); 
     } 

    } 

    public static void extendJsonObject(JsonObject destinationObject, ConflictStrategy conflictResolutionStrategy, JsonObject ... objs) 
      throws JsonObjectExtensionConflictException { 
     for (JsonObject obj : objs) { 
      extendJsonObject(destinationObject, obj, conflictResolutionStrategy); 
     } 
    } 

    private static void extendJsonObject(JsonObject leftObj, JsonObject rightObj, ConflictStrategy conflictStrategy) 
      throws JsonObjectExtensionConflictException { 
     for (Map.Entry<String, JsonElement> rightEntry : rightObj.entrySet()) { 
      String rightKey = rightEntry.getKey(); 
      JsonElement rightVal = rightEntry.getValue(); 
      if (leftObj.has(rightKey)) { 
       //conflict     
       JsonElement leftVal = leftObj.get(rightKey); 
       if (leftVal.isJsonArray() && rightVal.isJsonArray()) { 
        JsonArray leftArr = leftVal.getAsJsonArray(); 
        JsonArray rightArr = rightVal.getAsJsonArray(); 
        //concat the arrays -- there cannot be a conflict in an array, it's just a collection of stuff 
        for (int i = 0; i < rightArr.size(); i++) { 
         leftArr.add(rightArr.get(i)); 
        } 
       } else if (leftVal.isJsonObject() && rightVal.isJsonObject()) { 
        //recursive merging 
        extendJsonObject(leftVal.getAsJsonObject(), rightVal.getAsJsonObject(), conflictStrategy); 
       } else {//not both arrays or objects, normal merge with conflict resolution 
        handleMergeConflict(rightKey, leftObj, leftVal, rightVal, conflictStrategy); 
       } 
      } else {//no conflict, add to the object 
       leftObj.add(rightKey, rightVal); 
      } 
     } 
    } 

    private static void handleMergeConflict(String key, JsonObject leftObj, JsonElement leftVal, JsonElement rightVal, ConflictStrategy conflictStrategy) 
      throws JsonObjectExtensionConflictException { 
     { 
      switch (conflictStrategy) { 
       case PREFER_FIRST_OBJ: 
        break;//do nothing, the right val gets thrown out 
       case PREFER_SECOND_OBJ: 
        leftObj.add(key, rightVal);//right side auto-wins, replace left val with its val 
        break; 
       case PREFER_NON_NULL: 
        //check if right side is not null, and left side is null, in which case we use the right val 
        if (leftVal.isJsonNull() && !rightVal.isJsonNull()) { 
         leftObj.add(key, rightVal); 
        }//else do nothing since either the left value is non-null or the right value is null 
        break; 
       case THROW_EXCEPTION: 
        throw new JsonObjectExtensionConflictException("Key " + key + " exists in both objects and the conflict resolution strategy is " + conflictStrategy); 
       default: 
        throw new UnsupportedOperationException("The conflict strategy " + conflictStrategy + " is unknown and cannot be processed"); 
      } 
     } 
    } 
} 
+1

Я проголосовал за возобновление вашего первоначального вопроса. https://stackoverflow.com/questions/34092373/merge-extend-json-objects-using-gson-in-java Я столкнулся с аналогичной проблемой и решил использовать https://github.com/fge/json -patch/blob/master/README.md # json-diff – fadedbee

4

Вы можете использовать

Map firstObject = new GSON().fromJson(json1, HashMap.class); 
    Map secondObject = new GSON().fromJson(json2, HashMap.class); 

// сливаться Карта firstObject и secondObject, как вы хотите, видеть this post

String resultJson = new GSON().toJson(resultMap); 
+1

Эта стратегия наивна, поскольку она просто добавляет любые значения, которые существуют во второй карте к первой карте. Он не обрабатывает, что делать, если есть конфликты (существуют в обоих объектах) или если значения не примитивны (объединение рекурсивных объектов и конкатенация массива) – bradvido

+2

Да, но вы можете объединить conflit вручную, используя только слияние двух HashMap –

+1

вручную !? действительно? – bradvido

0

Вы можете бросить один JSONObject к jsonaray, (вы можете проверить here), то вы можете добавить новый jsonarray в другой jsonobject или преобразовать jsonobject в jsonarray, а затем создать новый jsonobject.

jsonObject.add("property", jsonarray); 
Смежные вопросы