从JSON请求字符串中删除空数组/列表

时间:2013-09-22 00:58:05

标签: vb.net json.net

如何从JSON字符串中删除空数组和空列表?

我使用vb.net和json.net来实现这一点,但json.net无法从JSON字符串中删除空数组。我的JSON字符串是这样的:

{
    "jsonrpc": "2.0",
    "id": 1,
    "token": "tikenname",
    "method": "task.run",
    "params": {
        "commandList": [{
            "method": "Users.new",
            "params": {
                "userIds": "userid",
                "details": {
                    "credentials": {
                        "userName": "user",
                        "password": "pass"
                    },
                    "data": {
                        "rights": {},
                        "quota": {
                            "daily": {
                                "limit": {}
                            },
                            "weekly": {
                                "limit": {}
                            },
                            "monthly": {
                                "limit": {}
                            }
                        },
                        "wwwFilter": {}
                    },
                    "autoLogin": {
                        "addresses": {},
                        "addressGroup": {}
                    },
                    "vpnAddress": {},
                    "groups": {}
                }
            }
        },
        {
        "method": "set.save"
        }
        ]
    }
}

例如我想从我的字符串

中删除此部分
                    "data": {
                        "rights": {},
                        "quota": {
                            "daily": {
                                "limit": {}
                            },
                            "weekly": {
                                "limit": {}
                            },
                            "monthly": {
                                "limit": {}
                            }
                        },
                        "wwwFilter": {}
                    },
                    "autoLogin": {
                        "addresses": {},
                        "addressGroup": {}
                    },
                    "vpnAddress": {},
                    "groups": {}

这是我的班级:

Public Class Account
    Public Property jsonrpc As String
    Public Property id As Integer
    Public Property token As String
    Public Property method As String
    Public Property params As New AccountSetParams
End Class

Public Class AccountSetParams
    Public Property commandList As New List(Of AccountSetCommandlist)
End Class

Public Class AccountSetCommandlist
    Public Property method As String
    Public Property params As New AccountSetUserDetails
End Class

Public Class AccountSetUserDetails
    Public Property userIds() As String
    Public Property details As New AccountSetDetails
    Public Property domainId As String
End Class

Public Class AccountSetDetails 
    Public Property credentials As New AccountSetCredentials 
    Public Property fullName As String 
    Public Property data As New AccountSetData 
    Public Property autoLogin As New AccountSetAutologin 
    Public Property vpnAddress As New AccountSetVpnaddress 
    Public Property groups() As New AccountSetGroup 
End Class
...

1 个答案:

答案 0 :(得分:1)

它看起来并不像Json.Net提供了一种简单的方法来排除您正在描述的空列表或数组。从技术上讲,您要排除的大多数对象都不是空的:它们包含其他对象[包含其他对象...],这些对象是空的。

因此,要完成此操作,您需要使用递归下降来过滤掉“无用的”信息。我认为最好的方法可能是首先将对象图加载到JObject(或JArray),然后递归地将非空元素复制到新的JObject(或JArray从最深层向上工作。然后,您可以序列化副本以获得所需的精简JSON。这种方法允许您以通用方式处理任何对象结构。

这是一个应该做的技巧:

Function RemoveEmptyChildren(token As JToken) As JToken

    If token.Type = JTokenType.Object Then

        Dim copy As JObject = New JObject()

        For Each prop As JProperty In token.Children(Of JProperty)()

            Dim child As JToken = prop.Value
            If child.HasValues Then
                child = RemoveEmptyChildren(child)
            End If

            If Not IsEmpty(child) Then
                copy.Add(prop.Name, child)
            End If

        Next

        Return copy

    ElseIf token.Type = JTokenType.Array Then

        Dim copy As JArray = New JArray()

        For Each child As JToken In token.Children()

            If child.HasValues Then
                child = RemoveEmptyChildren(child)
            End If

            If Not IsEmpty(child) Then
                copy.Add(child)
            End If

        Next

        Return copy

    End If

    Return token

End Function

Function IsEmpty(token As JToken) As Boolean

    Return (token.Type = JTokenType.Array And Not token.HasValues) Or
           (token.Type = JTokenType.Object And Not token.HasValues) Or
           (token.Type = JTokenType.String And token.ToString() = String.Empty) Or
           (token.Type = JTokenType.Null)

End Function

以下是演示如何使用该功能的简短示例:

Dim jsonString As String = _
    "{" + _
        """Int"" : 1," + _
        """String"" : ""Foo""," + _
        """EmptyString"" : """"," + _
        """EmptyArray"" : []," + _
        """EmptyObject"" : {}," + _
        """NullValue"" : null," + _
        """ArrayOfEmptyChildren"" : [ [], {}, """", null ]," + _
        """ChildObjectWithEmptyValues"" : {" + _
            """Array"" : []," + _
            """Object"" : {}," + _
            """Null"" : null," + _
            """String"" : """"" + _
        "}," + _
        """Boolean"" : true" + _
    "}"

Dim token As JToken = RemoveEmptyChildren(JToken.Parse(jsonString))

Console.WriteLine(token.ToString(Formatting.Indented))

这是上面例子的输出。请注意,只剩下非空信息。

{
  "Int": 1,
  "String": "Foo",
  "Boolean": true
}

注意:如果从对象而不是JSON字符串开始,您仍然可以使用此函数。只需使用JToken.Parse(jsonString)替换上例中的JToken.FromObject(yourObject)

此外,如果您想更改已删除的内容或未从输出中删除的内容,您可以修改IsEmpty功能以满足您的需求。

希望这有帮助。