使用JSON.net序列化数据表,如何阻止它转义其中一列中的JSON字符串

时间:2013-06-14 01:10:13

标签: vb.net json.net

我正在使用JSON.NET在VB.net中序列化这样的数据表,并且它工作正常:

ResultJSONString = JsonConvert.SerializeObject(MyDataTable)

问题是我将另一列(名为JSON_Column)添加到具有JSON字符串作为值的数据表中,现在当我序列化数据表时,SerializeObject方法使用该列中的JSON字符串中的引号转义反斜杠,所以我最终得到的JSON看起来像这样:

"ColumnA": "Value1",
"JSON_Column": "{\"SomePropertyName\":\"SomeValue\"}"

如何告诉JSONConvert.SerializeObject方法我的数据表的JSON_Column中的字符串值不应该被转义,因为它们本身就是JSON?

换句话说,我希望这样做:

"ColumnA": "Value1",
"JSON_Column": {"SomePropertyName": "SomeValue"}

它有点类似于this question,但我从数据表而不是自定义对象进行序列化,所以我不能使用该方法。

感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

您需要编写自定义转换器以将DataTable转换为JSON字符串。您只能告诉JsonConvert如何转换类型,因此您需要为DataTable提供转换器。

DataTable序列化为一个对象数组,其属性对应于一行中的每个值。您将首先反序列化JSON_Column列,以便将其视为对象而不是字符串。创建DataTable的这个新表示后,您可以让序列化程序处理其余部分。

以下是编写这样一个转换器的方法:

Class MyDataTableConverter
    Inherits JsonConverter

    Public Overrides Function CanConvert(type As Type) As Boolean
        Return type = GetType(DataTable)
    End Function

    Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
        Dim dt = TryCast(value, DataTable)
        If dt IsNot Nothing Then
            Dim rowSerializer = New MyRowSerializer
            Dim obj = New JArray(
                From row In dt.Rows.Cast(Of DataRow)
                Select rowSerializer.Serialize(dt, row.ItemArray)
            )
            serializer.Serialize(writer, obj)
        End If
    End Sub

    Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
        If existingValue Is Nothing Then
            Dim dt = CreateTable
            Dim rowSerializer = New MyRowSerializer
            Dim arr = serializer.Deserialize(Of JArray)(reader)
            For Each obj In arr.Cast(Of JObject)
                dt.Rows.Add(rowSerializer.Deserialize(dt, obj))
            Next
            Return dt
        End If
        Return existingValue
    End Function

    Private Function CreateTable() As DataTable
        Dim dt = New DataTable
        dt.Columns.Add("ColumnA", GetType(String))
        dt.Columns.Add("JSON_Column", GetType(String))
        Return dt
    End Function

    Class MyRowSerializer

        Public Function Serialize(table As DataTable, values As Object()) As JObject
            return New JObject(
                From x in table.Columns.Cast(Of DataColumn).Zip(values, Function(col, value) New With { col.ColumnName, .ColumnValue = value })
                Let value = SerializeColumn(x.ColumnName, x.ColumnValue)
                Select New JProperty(x.ColumnName, value)
            )
        End Function

        Private Function SerializeColumn(name As String, value As Object) As Object
            Select Case name
                Case "JSON_Column"
                    Return JsonConvert.DeserializeObject(DirectCast(value, String))
                Case Else
                    Return value
            End Select
        End Function

        Public Function Deserialize(table As DataTable, obj As JObject) As Object()
            Dim values = From col In table.Columns.Cast(Of DataColumn)
                         Let columnName = col.ColumnName
                         Let value = obj(columnName)
                         Select DeserializeColumn(columnName, value)
            return values.ToArray
        End Function

        Private Function DeserializeColumn(name As String, value As Object) As Object
            Select Case name
                Case "JSON_Column"
                    Return JsonConvert.SerializeObject(value)
                Case Else
                    Return value
            End Select
        End Function

    End Class

End Class

然后将传入转换器的表序列化为参数。

Dim json = JsonConvert.SerializeObject(dataTable, New MyDataTableConverter)