【问题标题】:JSONObject remove empty value pairsJSONObject 删除空值对
【发布时间】:2015-09-11 09:39:24
【问题描述】:

这是我的 Json 文件:

{  
   "models":{},
   "path":[  
      {  
         "path":"/web-profiles",
         "operations":[  
            {  
               "type":"",
               "responseMessages":[]
            }
         ]
      }
   ],
   "produces":[]
}

如果键的值为空(包括 []、""、{})。如何从 Json 文件中删除这些对。

  1. 我尝试使用 JSONObject 内置函数来删除不必要的对。但是,它不起作用。
  2. 我尝试使用字符串方法逐行处理。它有太多案例,我无法在我的代码中涵盖所有这些案例。 (例如,子键 'operations',当你想删除所有空值时,这个 key(operations) 值对也应该被删除。) 有什么想法吗?

【问题讨论】:

标签: java json string format jsonobject


【解决方案1】:

首先,您应该将json 反序列化为Map<String, Object>。 其次,循环映射条目以找出哪个键具有空值或哪个键具有值是ArrayList 的实例但为空并从Map 中删除。 最后,将Map序列化为json

试试这个代码:

String json = "{'a': 'apple', 'b': 'ball', 'c': 'cat', 'd': null, 'e': []}";
Type type = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> data = new Gson().fromJson(json, type);

for (Iterator<Map.Entry<String, Object>> it = data.entrySet().iterator(); it.hasNext();) {
    Map.Entry<String, Object> entry = it.next();
    if (entry.getValue() == null) {
        it.remove();
    } else if (entry.getValue() instanceof ArrayList) {
        if (((ArrayList<?>) entry.getValue()).isEmpty()) {
            it.remove();
        }
    }
}

json = new GsonBuilder().setPrettyPrinting().create().toJson(data);
System.out.println(json);

【讨论】:

  • Type、TypeToken、GsonBuilder、Gson..这些api的任何jar..?
【解决方案2】:

正则表达式解决方案

在使用 JSONParser 解析数据之前,您可以使用 REGEX 从数据中删除包含 ""、[] 或 {} 的任何行。

这样的正则表达式看起来像。请记住,您可能需要根据您的操作系统调整换行符

[^\n]*(\"(\n)*\"|\[(\n)*\]|\{(\n)*\})[^\n]*

为了说明JSON数据如下的一个实例

{  
   "models":{},
   "path":[  
      {  
         "path":"/web-profiles",
         "operations":[  
            {  
               "nickname":"",
               "type":"",
               "responseMessages":[]
            }
         ]
      }
   ],
   "produces":[]
}

第一次运行 replaceAll 时,结果为

{  
   "path":[  
      {  
         "path":"/web-profiles",
         "operations":[  
            {  
            }
         ]
      }
   ],
}

现在我们在“操作”JSONArray 中创建了一个空的 JSONObject。所以需要再次调用这个 replaceAll 函数,直到 JSON 字符串与之前的状态没有任何变化。

请记住,如果您在数据输入期间使用 readLine() 之类的函数,它可能会删除换行符,这会使该方法不起作用。所以解决这个问题,用这个替换你的阅读行。

json += in.readLine() + '\n';

这是我编写的一个快速程序,它从原始字符串中实际删除空 json 对象。

public static void main(String[] args){
    // String from above example with newline characters intact
    String json = "{\n\"models\":{},\n\"path\":[\n{\n\"path\":\"/web-profiles\",\n\"operations\":[\n{\n\"nickname\":\"\",\n\"type\":\"\",\n\"responseMessages\":[]\n}\n]\n}\n],\n\"produces\":[]\n}";

    // Value from the last iteration of the while loop
    String last = "";
    // If there was no change from the last replaceAll call stop
    while( !last.equals(json) ){
        last = json;
        // Same regex as above just escaped to work in a Java String
        json = json.replaceAll("[^\\n]*(\\{(\\n)*\\}|\\\"(\\n)*\\\"|\\[(\\n)*\\])[^\\n]*\\n","");
    }

    System.out.println(json);
}

【讨论】:

    【解决方案3】:

    如果您使用 javax.api API:

    public static JsonArray removeNull(JsonArray array) {
        JsonArrayBuilder builder = Json.createArrayBuilder();
        int i = 0;
        for (Iterator<JsonValue> it = array.iterator(); it.hasNext(); ++i) {
            JsonValue value = it.next();
            switch (value.getValueType()) {
            case ARRAY:
                JsonArray a = removeNull(array.getJsonArray(i));
                if (!a.isEmpty())
                    builder.add(a);
                break;
            case OBJECT:
                JsonObject object = removeNull(array.getJsonObject(i));
                if (!object.isEmpty())
                    builder.add(object);
                break;
            case STRING:
                String s = array.getString(i);
                if (s != null && !s.isEmpty())
                    builder.add(s);
                break;
            case NUMBER:
                builder.add(array.getJsonNumber(i));
                break;
            case TRUE:
            case FALSE:
                builder.add(array.getBoolean(i));
                break;
            case NULL:
                break;
            }
        }
        return builder.build();
    }
    
    public static JsonObject removeNull(JsonObject obj) {
        JsonObjectBuilder builder = Json.createObjectBuilder();
        for (Iterator<Entry<String, JsonValue>> it = obj.entrySet().iterator(); it.hasNext();) {
            Entry<String, JsonValue> e = it.next();
            String key = e.getKey();
            JsonValue value = e.getValue();
            switch (value.getValueType()) {
            case ARRAY:
                JsonArray array = removeNull(obj.getJsonArray(key));
                if (!array.isEmpty())
                    builder.add(key, array);
                break;
            case OBJECT:
                JsonObject object = removeNull(obj.getJsonObject(key));
                if (!object.isEmpty())
                    builder.add(key, object);
                break;
            case STRING:
                String s = obj.getString(key);
                if (s != null && !s.isEmpty())
                    builder.add(key, s);
                break;
            case NUMBER:
                builder.add(key, obj.getJsonNumber(key));
                break;
            case TRUE:
            case FALSE:
                builder.add(key, obj.getBoolean(key));
                break;
            case NULL:
                break;
            }
        }
        return builder.build();
    }
    
    @Test
    public void testRemoveNullJsonObject() {
        String str = ""
            + "{"
            + "   \"models\":{},"
            + "   \"path\":["
            + "      {"
            + "         \"path\":\"/web-profiles\","
            + "         \"operations\":["
            + "            {"
            + "               \"nickname\":\"CreateAWebExperienceProfile\","
            + "               \"type\":\"\","
            + "               \"responseMessages\":[]"
            + "            }"
            + "         ]"
            + "      }"
            + "   ],"
            + "   \"produces\":[]"
            + "}";
        JsonObject json = Json.createReader(new StringReader(str)).readObject();
        System.out.println(json);
        JsonObject removed = removeNull(json);
        System.out.println(removed);
        // -> {"path":[{"path":"/web-profiles","operations":[{"nickname":"CreateAWebExperienceProfile"}]}]}
    }
    

    【讨论】:

      【解决方案4】:

      不知道任何内置函数,但你可以试试这个

      public boolean cleanJSON(Object arg) throws JSONException{
          boolean valueExist = false;
          if(arg instanceof String){
              String str= (String)arg;
              if(!str.equals("")) valueExist = true;
          }else if(arg instanceof JSONObject){
              JSONObject obj = (JSONObject)arg;
              Iterator<String> iter = obj.keys();
              ArrayList<String> fields = new ArrayList<>();
              while(iter.hasNext())   fields.add(iter.next());
              for(String field:fields){
                  Object value = obj.get(field);
                  if(cleanJSON(value))    valueExist = true;
                  else                    obj.remove(field);
              }
          }else if(arg instanceof JSONArray){
              JSONArray arr = (JSONArray)arg;
              for(int i=0;i<arr.length();i++){
                  if(cleanJSON(arr.get(i)))   valueExist = true;
                  else{
                      arr.remove(i);
                      i--;
                  }
              }
          }
          return valueExist;
      }
      

      这将从空字段中清除您的 json 对象(它以递归方式工作)。所以如果 JSON 看起来像这样:

      "operations":[  
      {  
           "nickname":"",
           "type":"",
           "responseMessages":[]
      }]
      

      字段“操作”也将被删除。

      注意:JSONArray.remove 仅适用于以上 API 19

      【讨论】:

        【解决方案5】:

        在带有org.json 库的Scala 中,可以轻松地转换为Java(虽然有点冗长)。递归删除nulls 和空对象/数组:

        import org.json.{ JSONArray, JSONObject }
        
        object JsonCleaner {
        
          def clean(json: JSONObject): Boolean = {
            val i = json.keys()
            while (i.hasNext) clean(i, json.get(i.next()))
            json.length == 0
          }
        
          def clean(json: JSONArray): Boolean = {
            val i = json.iterator()
            while (i.hasNext) clean(i, i.next())
            json.length == 0
          }
        
          private def clean(i: java.util.Iterator[_], v: Any) {
            v match {
              case o: JSONObject =>
                if (clean(o)) i.remove()
              case a: JSONArray =>
                if (clean(a)) i.remove()
              case JSONObject.NULL | "" =>
                i.remove()
              case _ =>
            }
          }
        
        }
        

        【讨论】:

          【解决方案6】:

          这应该可以解决问题::

                                  Iterator<String> keys = jsonObject.keys();
                                  while(keys.hasNext()) {
                                      String key = keys.next();
                                      boolean propertyValuePresent = jsonObject.get(key) != null 
                                      && jsonObject.get(key)!="null"
                                      && !jsonObject.get(key).toString().isEmpty();     
                                      if(propertyValuePresent){
                                          jsonObject.remove(key);
                                      }
                                  }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-07-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多