This is my query:
SELECT
a.Id, a.Title,
(SELECT m.Id, m.Name, m.MobileNo
FROM [msm].[MsmMember] AS m
WHERE m.Id = a.MemberId
AND m.OrganizationId = @OrganizationId
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) AS Member
FROM
msm.MsmArticleSubmission a
WHERE
a.OrganizationId = @OrganizationId
AND a.Id = @Id
FOR JSON PATH
This is the resulting output:
[
{
"Id": "A4C6B579-5D0C-4807-9537-53C6B1E8E6BA",
"Title": "Test Data",
"Member": "{"Id":"79F87A71-332A-43CB-A944-E8C50C00CFF7","Name":"Asma Husain Noora","MobileNo":"00000000"}"
}
]
Here Member is not a valid JSON Format, so, when I try to deserialize from C#, the Member
object throws an exception, because of the invalid JSON format. I couldn’t figure out any solution. It works if I make "Member" an Array, but I need a single associate object only.
Tech stack: ASP.NET Core 8.0, SQL Server 2019
2
Answers
try this :
The issue you’re facing stems from the fact that the
Member
sub-query is producing a JSON string that’s then being treated as a standard string in the context of the outer JSON query. Instead of the inner JSON being naturally integrated into the outer JSON, it’s being escaped and included as a simple string.One way to solve this is to parse the inner JSON string in the resultant JSON object in your application. However, this is not an ideal solution as it’s not efficient and requires unnecessary parsing.
The better solution is to format the JSON correctly in your SQL query itself, so that the
Member
object is a nested JSON object within the outer JSON, rather than a JSON-formatted string. Unfortunately, SQL Server doesn’t have a built-in function that directly casts a JSON string to a JSON object in the way that you want.Here’s a technique you can use to integrate the inner JSON into the outer JSON by using the
OPENJSON
andCROSS APPLY
clauses:Here’s what’s happening in this query:
CROSS APPLY
takes the sub-query JSON string and exposes it as a named JSON Content (MemberJSON.JsonContent
).CROSS APPLY
withOPENJSON
then parses that JSON string back into SQL rows, with theWITH
clause casting the JSON values back to their proper SQL types and names.Member.*
), which allows the JSON to be integrated without additional string escaping.With this technique,
Member
should now be a properly integrated nested JSON object in your result, so when you query, it will return a valid JSON object instead of a JSON string forMember
.