java JSONObject 删除空值对

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31039207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:58:41  来源:igfitidea点击:

JSONObject remove empty value pairs

javajsonstringformatjsonobject

提问by A Phototactic Coder

Here is my Json File:

这是我的 Json 文件:

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

If the values of keys are empty (includes [], "", {}). How can I remove those pairs from Json file.

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

  1. I tried to use JSONObject build-in functions to remove unnecessary pairs. But, it didn't work.
  2. I tried to use string method to process it line by line. It got too many cases, I can't cover all of those cases in my code. (for example, the sub-key 'operations', when you want to remove all empty value, this key(operations) value pair also should be removed.) Any ideas?
  1. 我尝试使用 JSONObject 内置函数来删除不必要的对。但是,它没有用。
  2. 我尝试使用字符串方法逐行处理它。案例太多了,我无法在我的代码中涵盖所有这些案例。(例如,子键'operations',当你想删除所有空值时,这个键(操作)值对也应该被删除。)有什么想法吗?

回答by codeaholicguy

First, you should deserialize jsonto a Map<String, Object>. Second, loop the map entry to find out what key has null value or what key has value is instance of ArrayListbut empty and remove from the Map. Last, serialize the Mapto json.

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

Try this code:

试试这个代码:

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);

回答by egtoney

Regex solution

正则表达式解决方案

You could use REGEX to remove any line from your data that conatins a "",[],or {} before you parse it with the JSONParser.

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

The regex for something like this would look like. Keep in mind that you may have to adjust the new line character depending on your OS

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

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

To account for an instance where the JSON data is as follows

以JSON数据如下为例

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

The first time you run that replaceAll it will result with

第一次运行该 replaceAll 时,它将导致

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

Now we an empty JSONObject inside of the "operations" JSONArray. So this replaceAll function needs to be called again untill the JSON String doesn't have any changes from it's previous state.

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

Keep in mind that if you use functions like readLine() during data input it can remove the newline character which will make this method not work. So solve this replace your read line with this.

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

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

Here is a quick program I wrote that does the actual removal of empty json objects from the original String.

这是我编写的一个快速程序,它从原始字符串中实际删除空的 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);
}

回答by saka1029

If you use javax.api API:

如果您使用 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"}]}]}
}

回答by fchristysen

Don't know about any build-in functions but you could try this

不知道任何内置功能,但你可以试试这个

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;
}

That would clean your json object from empty field(it work recursively). So if the JSON looks like this:

这将从空字段中清除您的 json 对象(它以递归方式工作)。因此,如果 JSON 如下所示:

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

field "operations" will also removed.

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

note : JSONArray.remove only work for API 19 above

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

回答by Leon Stein

In Scala with org.jsonlibrary, can be easily converted to Java (although a bit more verbose). Recursively removes nulls and empty objects/arrays:

在带有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 _ =>
    }
  }

}

回答by Johnny Alpha

This should do the trick::

这应该可以解决问题::

                        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);
                            }
                        }