2

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

ResultJSONString = JsonConvert.SerializeObject(MyDataTable)

问题是我在以 JSON 字符串作为值的数据表中添加了另一列(名为 JSON_Column),现在当我序列化数据表时,SerializeObject 方法用反斜杠转义了该列中 JSON 字符串中的引号,所以我最终得到如下所示的 JSON:

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

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

换句话说,我想要这样的结果:

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

它有点类似于这个问题,但我是从数据表序列化,而不是自定义对象,所以我不能使用那个方法。

谢谢你的帮助!

4

1 回答 1

4

You'll need to write a custom converter to convert that DataTable to a JSON string. You can only tell JsonConvert how to convert types so you'll need to provide a converter for DataTable.

A DataTable is serialized as an array of objects with a property corresponding to each of the values in a row. You'll want to deserialize the JSON_Column column first so it is treated as an object and not a string. Once you created this new representation of your DataTable, you can let the serializer take care of the rest.

Here's how you could write such a converter:

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

Then serialize your table passing in the converter as an argument.

Dim json = JsonConvert.SerializeObject(dataTable, New MyDataTableConverter)
于 2013-06-15T04:08:22.023 回答