如何将子JSON结构转换为C#对象图

如何将子JSON结构转换为C#对象图

问题描述:

我正在使用SQL Server 2016的FOR JSON将SQL Server SELECT语句转换为JSON字符串。我的意图是让C#将生成的JSON字符串转换为对象。如何将子JSON结构转换为C#对象图

SQL Server服务器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(一个用于PhoneNumberList本身,另一个用于整个SELECT语句),这导致PhoneNumberList被转换为一个没有被转换成一个字符串的字符串阵列。

如何将表示电话号码集合的子字符串转换为IPhoneNumberDataContract数组?

+3

'...生日,JSON_QUERY(SELECT ...)'。 –

+0

将PersonDataContract的PhoneNumberList设置为字符串,然后将每个字符串反序列化为PhoneNumberDataContract。 –

+0

@JeroenMostert - 你的建议解决了这个问题。你能回答这个问题吗?我可以接受它。谢谢。 –

这是排序覆盖the FAQ

问题。我有JSON文本存储在表列中。我想将它包含在FOR JSON的输出中。但FOR JSON逃脱在JSON所有 字符,所以我得到一个JSON字符串,而不是一个 嵌套的对象[..]

答案。存储在文本列或文字中的JSON与任何文本一样被对待。也就是说,它被双引号包围并逃脱。如果 要返回转义的JSON对象,通过JSON列 的一个参数JSON_QUERY函数[..]

它没有明确提到使用FOR JSON也将任何不平凡的子查询产生一个转义值,并以这种方式要求JSON_QUERY。因此,使用

SELECT 
    Id AS PersonId, 
    FirstName, 
    LastName, 
    Name, 
    Birthday, 
    JSON_QUERY(
     SELECT 
      ... 
     FOR JSON PATH,INCLUDE_NULL_VALUES  
    ) AS PhoneNumberList 

通过“不平凡”,我的意思是,像这样的查询会要求JSON_QUERY

SELECT 
    'Foo' AS Foo, (
     SELECT 1 AS A 
     FOR JSON PATH 
    ) AS Bar 
FOR JSON PATH 

Bar这里将不再逃脱,因为优化显然会记住它的处理JSON。我还没有找到一套统一的规则来管理这个(different question, same issue),并且它甚至不清楚这是否是有意的行为或错误,但JSON_QUERY不管你怎么做。它可能总是被使用,以防止查询从“简单”到“复杂”并突然需要它的意外。