我寫了一個存儲程序來完成任意JSON到camelcase的轉換。它涵蓋了我能想到的大多數數據類型,但可能有一些JSON會打破它。我希望它是一個函數,但是你不能在一個函數中執行動態sql。
CREATE PROCEDURE [dbo].[CamelCaseJson] (
@jsonIn nvarchar(max),
@jsonOut nvarchar(max) output
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @isArray BIT = 0
DECLARE @innerCols NVARCHAR(MAX)
DECLARE @outerCols NVARCHAR(MAX)
DECLARE @sql NVARCHAR(MAX)
IF LEFT(@jsonIn, 1) = '['
BEGIN
SET @isArray = 1
END
CREATE TABLE #tmpData (
[rownum] INT IDENTITY(1, 1),
[key] NVARCHAR(MAX),
[value] NVARCHAR(MAX),
[type] INT,
[processedKey] NVARCHAR(MAX),
[processedValue] NVARCHAR(MAX)
)
DECLARE @jsons TABLE (
[rownum] INT,
[json] NVARCHAR(MAX)
)
INSERT #tmpData (
[key],
[value],
[type],
[processedKey],
[processedValue]
)
SELECT
[key],
[value],
[type],
LOWER(SUBSTRING([key], 1, 1)) + SUBSTRING([key], 2, 999999999),
[value]
FROM OPENJSON(@jsonIn)
INSERT @jsons (
[rownum],
[json]
)
SELECT
[rownum],
[value]
FROM #tmpData
WHERE [type] in (4, 5)
DECLARE @id INT
DECLARE @subJsonIn NVARCHAR(MAX)
DECLARE @subJsonOut NVARCHAR(MAX)
WHILE EXISTS (SELECT 1 FROM @jsons)
BEGIN
SET @subJsonOut = NULL
SELECT
TOP 1
@id = [rownum],
@subJsonIn = [json]
FROM @jsons
EXEC [dbo].[CamelCaseJson] @subJsonIn, @subJsonOut OUTPUT
UPDATE #tmpData
SET [processedValue] = @subJsonOut
WHERE [rownum] = @id
DELETE @jsons WHERE [rownum] = @id
end
IF @isArray = 0
BEGIN
SELECT @innerCols = COALESCE(@innerCols + ', ', '') + QUOTENAME([processedKey]) FROM #tmpData
SELECT @outerCols =
COALESCE(@outerCols + ', ', '')
+ CASE
WHEN [type] = 2 AND [value] LIKE '%e%' THEN 'CAST(' + QUOTENAME([processedKey]) + ' AS FLOAT) AS ' + QUOTENAME([processedKey])
WHEN [type] = 2 AND [value] LIKE '%.%' THEN 'CAST(' + QUOTENAME([processedKey]) + ' AS DECIMAL(19, 7)) AS ' + QUOTENAME([processedKey])
WHEN [type] = 2 THEN 'CAST(' + QUOTENAME([processedKey]) + ' AS INT) AS ' + QUOTENAME([processedKey])
WHEN [type] = 3 THEN 'CAST(' + QUOTENAME([processedKey]) + ' AS BIT) AS ' + QUOTENAME([processedKey])
WHEN [type] in (4, 5) THEN 'JSON_QUERY(' + QUOTENAME([processedKey]) + ') AS ' + QUOTENAME([processedKey])
ELSE QUOTENAME([processedKey])
END
FROM #tmpData
SET @sql = '
WITH pv AS (
SELECT
[dummy] = 1,
[key] = [processedKey],
[value] = [processedValue]
FROM #tmpData
)
SELECT @dynout = (
SELECT ' + @outerCols + '
FROM (
SELECT [dummy], ' + @innerCols + '
FROM pv
PIVOT (
MAX([value]) FOR [key] IN (' + @innerCols + ')
) pvresult
) x
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER, INCLUDE_NULL_VALUES
)
'
EXEC sp_executesql @sql, N'@dynout NVARCHAR(MAX) OUT', @jsonOut OUTPUT
END
ELSE
BEGIN
SELECT @jsonOut =
COALESCE(@jsonOut + ',', '') +
CASE
WHEN [type] = 1 THEN '"' + [processedValue] + '"'
ELSE [processedValue]
END
FROM #tmpData
ORDER BY [rownum]
SET @jsonOut = '[' + @jsonOut + ']'
END
DROP TABLE #tmpData
END
GO
要檢查你的例子:
DECLARE @jsonIn NVARCHAR(MAX)
DECLARE @jsonOut NVARCHAR(MAX)
SET @jsonIn = (
SELECT
[Id] = 3,
[SId] = '5801',
[Name] = 'Pizza',
[Type] = 'Error'
FOR JSON PATH
)
EXEC [dbo].[bh_CamelCaseJson] @jsonIn, @jsonOut OUTPUT
SELECT @jsonIn [Json]
UNION ALL
SELECT @jsonOut [Json]
給你
在[{ 「ID」:3, 「SID」: 「5801」, 「姓名」:「比薩「]」Type「:」Error「}]
Out [{」id「:3,」sId「:」5801「,」name「:」Pizza「,」type「:」Error「}]
我的單元測試JSON(不漂亮格式化的,不好意思):
{"Pnull":null,"Pstring":"Foo","Pint":1,"Pdec":1.3,"Pbool":true,"Pstrarray":["a","b"],"Pintarray":[1,3,5],"Parray":[{"Prop":"val1"},{"Prop":"val2"}],"Pjson":{"Subproperty":1},"Pjsonstring":"{\"Subproperty\":2}","Poffset":"2017-06-20T22:18:31.2279221-04:00","DeepObj":{"Level":2,"Sub":{"Level":3,"Sub":{"Level":4,"Sub":{"Level":"Basement"}}}},"Flt":1.3e-9}
這種解決方案不能轉換爲駝峯。我想要屬性Id,Sid被camelcased即id,sid,名稱 – pankaj
JSON反序列化不會更改目標屬性名稱或它的大小寫。由於您的目標類型是動態的,因此它將使用與JSON字符串中相同的屬性名稱和外殼。如果你想要屬性名稱和自己的方式,那麼你需要定義一個具有用JsonProperty屬性裝飾的屬性的類。 –
'JsonSerializerSettings'用於在序列化時序列化和正確讀取屬性名稱的同時生成具有所需外殼的JSON字符串。我不會更改它的反序列化類型的屬性的名稱或大小寫。 –