我正在使用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,但我从数据表而不是自定义对象进行序列化,所以我不能使用该方法。
感谢您的帮助!
答案 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)