无键读取json数组的USQL调用

无键读取json数组的USQL调用,json,azure,azure-data-lake,u-sql,Json,Azure,Azure Data Lake,U Sql,我有一个嵌套的json,我正试图在usql中扁平化它。我无法共享数据,但结构与此类似 { "userlist": [user1, user1], "objects": { "largeobjects": [object1, object2, object3] "smallobjects": [s_object1, s_object2] }, "applications": [{ "application":

我有一个嵌套的json,我正试图在usql中扁平化它。我无法共享数据,但结构与此类似

{
    "userlist": [user1, user1],
    "objects": {
        "largeobjects": [object1, object2, object3]
        "smallobjects": [s_object1, s_object2]
    },
    "applications": [{
            "application": sdq3ds5dsa
        }, {
            "application": dksah122j4
        }, {
            "application": sadsw2dq2s
        }, {
            "application": pro3dfdsn3
        }
    ],
    "date" : 12344232,
    "timezone" : "Asia",
    "id" : "sad2ddssa2",
    "admin": {
        "lang": "eng",
        "country": "us",
    }
}
我使用定制的jsonoutputter从json文件中提取,并使用jsontuple函数提取值。我的问题是该函数使用sql映射生成键值对。这适用于我有一个键的情况,但当我试图使用该函数从无键数组获取值时,它会抛出一个错误

任何关于如何解决这一问题的建议都将不胜感激

编辑 这是我正在关注的输出:

sad2ddssa2,object1,12344232,亚洲,英国,美国, sad2ddssa2,object2,12344232,亚洲,英国,美国

尝试在u-sql中使用散文。使用散文的c nuget处理数据并进行复杂的提取。这是一个非常强大的人工智能软件包。请参见此处的视频和示例:

第二种选择

创建一个c函数来处理json。类似于此,使用c json api使此示例适应您的自定义提取请求:

/* Formats the array of values into a named json array. */

DECLARE @JsonArray Func<SqlArray<string>, string, string> = (data, name) => 
    {
        StringBuilder buffer = new StringBuilder();

        buffer.Append("{\r\n\t\"" + name + "\": [\r\n");

        for (int i = 0; i < data.Count(); i++)
        {
            if (i > 0)
            {
                buffer.Append(",\r\n");
            }

            buffer.Append("\t\"" + data[i] + "\"");
        }

        buffer.Append("\r\n\t]\r\n}");

        return buffer.ToString();
    };

/* Format the array containing groups of comma separated values into a named json array */

@Query = 
    SELECT
        @JsonArray(SubscriptionArray, "subscriptionList") AS JsonArray
    FROM @subscriptionsQuery1;
第三种选择

根据您的需要调整后,尝试这种方法:

/* For each json line create a json map (SqlMap) */

@subscriptionsQuery1 = 
    SELECT 
           JsonFunctions.JsonTuple(JsonLine) AS JsonMap
    FROM @SubscriptionsExtractor AS t;

/* For each json map get the required property value */

@subscriptionsQuery1 = 
    SELECT DISTINCT
           JsonMap["alias"] AS Subscription
    FROM @subscriptionsQuery1 AS t;

/* Join the value of all rows into a single row containing an array of all values */

@subscriptionsQuery1 = 
    SELECT
        ARRAY_AGG<string>(Subscription) AS SubscriptionArray
    FROM @subscriptionsQuery1 AS t;

我能够使用NewtonSoft MultiLevelJsonExtractor提取器和:

我的结果:


我想说,这可能比使用roll your own方法更安全,因为NewtonSoft库专门用于处理JSON,并且经过了尝试和测试。

请发布一些有效的JSON,即使它是虚构的。你的预期结果是什么?@wBob,我已经编辑了这个问题,希望这能提供更多的信息。谢谢你,对于我以后的一些任务,散文看起来很有趣。第三种方法是我尝试做的,但是json tuple需要一个sql.map,我的数组只有值,没有键,并且生成一个不兼容的sql.array,因此我的问题。最后,我编写了自定义代码来完成扁平化。我相信这不是最优雅的解决方案,也许我已经知道如何使用现有的功能,但它是有效的。不过,我会接受这个答案,因为散文在将来会对我有用。你也可以尝试第二种方法。使用json.NETAPI解析json字符串,您不需要平铺文件。有趣的方法是@MiguelDomingues+10。
REFERENCE ASSEMBLY [Newtonsoft.Json];
REFERENCE ASSEMBLY [Microsoft.Analytics.Samples.Formats]; 

USING Microsoft.Analytics.Samples.Formats.Json;

DECLARE @inputFile string = @"\input\yourInputJSON.json";
DECLARE @outputFile string = @"\output\output.csv";


@input =
    EXTRACT id string,
            largeobjects string,
            date string,
            timezone string,
            lang string,
            country string
    FROM @inputFile
    USING new MultiLevelJsonExtractor("objects", false,
          "id",
          "largeobjects",
          "date",
          "timezone",
          "admin.lang",
          "admin.country"
          );

// Convert the JSON column to SQL MAP to multiple rows
@working =
    SELECT id,
           JsonFunctions.JsonTuple(largeobjects).Values AS largeobject,
           date,
           timezone,
           lang,
           country
    FROM @input;


// Explode the JSON SQL MAP
@output =
    SELECT id,
           x.y AS largeobject,
           date,
           timezone,
           lang,
           country
    FROM @working
         CROSS APPLY
             EXPLODE(largeobject) AS x(y);


OUTPUT @output
TO @outputFile
USING Outputters.Csv(quoting : false);