如何将子 JSON 结构转换为 C# 对象图
How to convert child JSON structure to C# object graph
我正在使用 SQL Server 2016 的 FOR JSON 将 SQL Server SELECT 语句转换为 JSON 字符串。我的意图是让 C# 将生成的 JSON 字符串转换为一个对象。
SQL服务器服务器select声明:
SELECT
Id AS PersonId,
FirstName,
LastName,
Name,
Birthday,
(
SELECT
PhoneNumber.PhoneNumberTypeId,
PhoneNumber.PhoneNumber
FROM
PhoneNumber
INNER JOIN PhoneNumberType ON PhoneNumber.PhoneNumberTypeId = PhoneNumberType.Id
WHERE
PhoneNumber.PersonId = Person.Id
FOR JSON PATH,INCLUDE_NULL_VALUES
) AS PhoneNumberList
FROM
Person
ORDER BY
LastName
FOR JSON PATH,INCLUDE_NULL_VALUES
C# 对象我正在尝试将数据转换为:
public class PersonDataContract : IPersonDataContract
{
public Int32 PersonId { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Name { get; set; }
public DateTime? Birthday { get; set; }
public Int32 Age { get; }
public IList<IPhoneNumberDataContract> PhoneNumberList { get; set; }
public PersonDataContract()
{
PhoneNumberList = new List<IPhoneNumberDataContract>();
}
}
原始 JSON:
[
{
"PersonId": 5,
"FirstName": "Squire",
"LastName": "Escrow",
"Name": "Squire Escrow",
"Birthday": "2001-12-12",
"PhoneNumberList": "[{\"PhoneNumberTypeId\":1,\"PhoneNumber\":\"8129091423\"}]"
},
{
"PersonId": 6,
"FirstName": "Vilhelm",
"LastName": "Huldsputh",
"Name": "Vilhelm Huldsputh",
"Birthday": "1953-11-13",
"PhoneNumberList": "[{\"PhoneNumberTypeId\":1,\"PhoneNumber\":\"9871237171\"},{\"PhoneNumberTypeId\":2,\"PhoneNumber\":\"8189991212\"}]"
}
]
将原始 JSON 转换为对象的代码:
...
using (DbDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{
var jsonString = reader.GetValue(0).ToString();
var list = JsonConvert.DeserializeObject<List<PersonDataContract>>(jsonString);
}
reader.Close();
}
只要我从原始 JSON 中删除 PhoneNumberList,此过程就有效。我认为问题是我在我的 SQL 语句中使用了 2 'FOR JSON PATH's(一个用于 PhoneNumberList 本身,一个用于整个 SELECT 语句)这导致 PhoneNumberList被转换为未转换为数组的字符串。
如何将表示 phone 个数字集合的子字符串转换为 IPhoneNumberDataContract 数组?
这是 中涵盖的 the FAQ:
Question. I have JSON text stored in a table column. I want to include it in the output of FOR JSON
. But FOR JSON
escapes all
characters in the JSON, so I'm getting a JSON string instead of a
nested object [..]
Answer. JSON stored in a text column or a literal is treated like any text. That is, it's surrounded with double quotes and escaped. If
you want to return an unescaped JSON object, pass the JSON column as
an argument to the JSON_QUERY
function [..]
它没有明确提到任何使用 FOR JSON
的非平凡子查询也会产生转义值,并且以这种方式需要 JSON_QUERY
。所以使用
SELECT
Id AS PersonId,
FirstName,
LastName,
Name,
Birthday,
JSON_QUERY(
SELECT
...
FOR JSON PATH,INCLUDE_NULL_VALUES
) AS PhoneNumberList
"non-trivial",我的意思是这样的查询不需要 JSON_QUERY
:
SELECT
'Foo' AS Foo, (
SELECT 1 AS A
FOR JSON PATH
) AS Bar
FOR JSON PATH
Bar
不会在这里转义,因为优化器显然记得它正在处理 JSON。我还没有找到一套一致的规则来管理这个 (),甚至不清楚这是有意为之的行为还是一个错误,但是 JSON_QUERY
无论如何都会帮助你.它可能应该始终被使用,以防止从 "simple" 到 "complex" 的查询突然需要它。
我正在使用 SQL Server 2016 的 FOR JSON 将 SQL Server SELECT 语句转换为 JSON 字符串。我的意图是让 C# 将生成的 JSON 字符串转换为一个对象。
SQL服务器服务器select声明:
SELECT
Id AS PersonId,
FirstName,
LastName,
Name,
Birthday,
(
SELECT
PhoneNumber.PhoneNumberTypeId,
PhoneNumber.PhoneNumber
FROM
PhoneNumber
INNER JOIN PhoneNumberType ON PhoneNumber.PhoneNumberTypeId = PhoneNumberType.Id
WHERE
PhoneNumber.PersonId = Person.Id
FOR JSON PATH,INCLUDE_NULL_VALUES
) AS PhoneNumberList
FROM
Person
ORDER BY
LastName
FOR JSON PATH,INCLUDE_NULL_VALUES
C# 对象我正在尝试将数据转换为:
public class PersonDataContract : IPersonDataContract
{
public Int32 PersonId { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Name { get; set; }
public DateTime? Birthday { get; set; }
public Int32 Age { get; }
public IList<IPhoneNumberDataContract> PhoneNumberList { get; set; }
public PersonDataContract()
{
PhoneNumberList = new List<IPhoneNumberDataContract>();
}
}
原始 JSON:
[
{
"PersonId": 5,
"FirstName": "Squire",
"LastName": "Escrow",
"Name": "Squire Escrow",
"Birthday": "2001-12-12",
"PhoneNumberList": "[{\"PhoneNumberTypeId\":1,\"PhoneNumber\":\"8129091423\"}]"
},
{
"PersonId": 6,
"FirstName": "Vilhelm",
"LastName": "Huldsputh",
"Name": "Vilhelm Huldsputh",
"Birthday": "1953-11-13",
"PhoneNumberList": "[{\"PhoneNumberTypeId\":1,\"PhoneNumber\":\"9871237171\"},{\"PhoneNumberTypeId\":2,\"PhoneNumber\":\"8189991212\"}]"
}
]
将原始 JSON 转换为对象的代码:
...
using (DbDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{
var jsonString = reader.GetValue(0).ToString();
var list = JsonConvert.DeserializeObject<List<PersonDataContract>>(jsonString);
}
reader.Close();
}
只要我从原始 JSON 中删除 PhoneNumberList,此过程就有效。我认为问题是我在我的 SQL 语句中使用了 2 'FOR JSON PATH's(一个用于 PhoneNumberList 本身,一个用于整个 SELECT 语句)这导致 PhoneNumberList被转换为未转换为数组的字符串。
如何将表示 phone 个数字集合的子字符串转换为 IPhoneNumberDataContract 数组?
这是 中涵盖的 the FAQ:
Question. I have JSON text stored in a table column. I want to include it in the output of
FOR JSON
. ButFOR JSON
escapes all characters in the JSON, so I'm getting a JSON string instead of a nested object [..]Answer. JSON stored in a text column or a literal is treated like any text. That is, it's surrounded with double quotes and escaped. If you want to return an unescaped JSON object, pass the JSON column as an argument to the
JSON_QUERY
function [..]
它没有明确提到任何使用 FOR JSON
的非平凡子查询也会产生转义值,并且以这种方式需要 JSON_QUERY
。所以使用
SELECT
Id AS PersonId,
FirstName,
LastName,
Name,
Birthday,
JSON_QUERY(
SELECT
...
FOR JSON PATH,INCLUDE_NULL_VALUES
) AS PhoneNumberList
"non-trivial",我的意思是这样的查询不需要 JSON_QUERY
:
SELECT
'Foo' AS Foo, (
SELECT 1 AS A
FOR JSON PATH
) AS Bar
FOR JSON PATH
Bar
不会在这里转义,因为优化器显然记得它正在处理 JSON。我还没有找到一套一致的规则来管理这个 (JSON_QUERY
无论如何都会帮助你.它可能应该始终被使用,以防止从 "simple" 到 "complex" 的查询突然需要它。