JSONObject 删除空值对

Posted

技术标签:

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

这是我的 Json 文件:

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

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

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

【问题讨论】:

***.com/a/23921129/2369266 的可能重复项 【参考方案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);
                            
                        

【讨论】:

以上是关于JSONObject 删除空值对的主要内容,如果未能解决你的问题,请参考以下文章

如果一个json string中含有“class”这个key, 那么利用JSONObjec.fromObject(string)得到的一个json object会丢失“class”信息

Java HashMap 与 JSONObject

如何比较Java中JsonObject的空值

保留空值——Java POJO 到 org.JSONObject

在grails中解析JSON时如何获取真正的空值而不是JSONObject.NULL值

Gson的JsonObject键值对遍历并做相应处理