【问题标题】:Camel Case JsonObject array in sql server2016sql server 2016 中的 Camelcase Json 对象数组
【发布时间】:2018-10-17 04:07:31
【问题描述】:

我使用“For JSON AUTO”从 SqlServer 2016 返回 Json 我的操作是这样的

"[{\"Id\":3,\"SId\":\"5801\",\"Name\":\"Pizza\",\"Type\":\"Error\"}]"

我正在使用以下代码反序列化数据

 public Someclass GetData(int Id)
    {
        using (var dataContext = new DataContext(_connectionString))
        {
               var serializer = new JsonSerializerSettings()
               {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
               };
            var dataArray = dataContext.ExecuteQuery<string>(query.ToString()).SingleOrDefault();
            dynamic obj= JsonConvert.DeserializeObject<dynamic>(dataArray , serializer);

            return obj
        }
    }

在 obj 对象中我没有得到驼峰数据。它的格式如下

 "{[{"Id":3,SId":"5801","Name":"Pizza","Type":"Error"}]}" 

由于我保存 json 结果的数据结构在这里是动态的,因此我无法使用 json.net 将其转换为驼峰式。是否有任何 sql 方法可以从 sql server 2016 返回驼峰式列名

【问题讨论】:

    标签: json.net sql-server-2016


    【解决方案1】:

    他们想要“select ... for json auto”的这个 json 输出:

    [{"id":3,"sId":"5801","name":"pizza","type":"Error"}]

    如果您直接在 javascript 中使用 SQL 输出,您可能会关心它不是驼峰式的。但是,在上面的代码中,SQL 是在 .NET 程序中使用的,并且 .NET 反序列化不区分大小写。无需使用动态类型或弄乱序列化程序设置。直接反序列化到SomeClass

    var someClass = JSONConvert.DeserializeObject&lt;SomeClass&gt;(dataArray)

    但请注意,您应该在 C# 代码中使用 C# 约定——因此 SomeClass 应该使用 Pascal 案例名称。如果您从 .NET WebApi 返回 SomeClass,那就是,您应该转换为驼峰式大小写。在 .NET Core 中,这是默认完成的。对于 .NET Framework,您可以在应用程序初始化时更改 JSON 序列化程序设置以执行相同的操作。

    但如果你真的想要:

    [{"id":3,"sId":"5801","name":"pizza","type":"Error"}]

    如果可以的话,修改查询本身,并在任何情况下明确列出列:

    select id, sId, name, type from ... for json auto

    【讨论】:

      【解决方案2】:

      我编写了一个存储过程来将任意 JSON 转换为驼峰式。它涵盖了我能想到的大多数数据类型,但可能有一些 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].[CamelCaseJson] @jsonIn, @jsonOut OUTPUT
      
      SELECT @jsonIn [Json]
      UNION ALL
      SELECT @jsonOut [Json]
      

      给你

      在 [{"Id":3,"SId":"5801","Name":"Pizza","Type":"Error"}]

      输出 [{"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}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多