自定义行定界符和json上的U-SQL自定义提取器

时间:2019-02-28 09:39:34

标签: c# azure-data-lake u-sql

我有几个具有以下数据结构的文本文件:

{
huge 
json 
block that spans across multiple lines
}
--#newjson#--
{
huge 
json 
block that spans across multiple lines
}
--#newjson#--
{
huge 
json 
block that spans across multiple lines
} etc....

实际上是由"--##newjson##--"字符串行分隔的json块。 我正在尝试编写一个客户提取程序来对此进行解析。问题是我不能使用string数据类型来提供json解串器,因为它的最大大小为128 KB,并且json块不适合此类型。使用自定义提取器解析此文件的最佳方法是什么?

我尝试使用下面的代码,但是不起作用。甚至行定界符"--#newjson#--"似乎也不正确。

public SampleExtractor(Encoding encoding, string row_delim = "--#newjson#--", char col_delim = ';')
{
    this._encoding = ((encoding == null) ? Encoding.UTF8 : encoding);
    this._row_delim = this._encoding.GetBytes(row_delim);
    this._col_delim = col_delim;
}

public override IEnumerable<IRow> Extract(IUnstructuredReader input, IUpdatableRow output)
{ 
    //Read the input  by json
    foreach (Stream current in input.Split(_encoding.GetBytes("--#newjson#--")))
    {
        var serializer = new JsonSerializer();

        using (var sr = new StreamReader(current))
        using (var jsonTextReader = new JsonTextReader(sr))
        {
            var jsonrow = serializer.Deserialize<JsonRow>(jsonTextReader); 
            output.Set(0, jsonrow.status.timestamp);
        }
        yield return output.AsReadOnly();
    }
} 

2 个答案:

答案 0 :(得分:0)

以下是实现解决方案的方法:

1)创建与您的JSON对象等效的c# 注意:-假设您的所有json对象在文本文件中都相同。 例如:

Json代码

{
        "id": 1,
        "value": "hello",
        "another_value": "world",
        "value_obj": {
            "name": "obj1"
        },
        "value_list": [
            1,
            2,
            3
        ]
    }

等效于C#

 public class ValueObj
    {
        public string name { get; set; }
    }

    public class RootObject
    {
        public int id { get; set; }
        public string value { get; set; }
        public string another_value { get; set; }
        public ValueObj value_obj { get; set; }
        public List<int> value_list { get; set; }
    }

2)在完成基于定界符的分割之后,请像下面那样更改反序列化代码

using (JsonReader reader = new JsonTextReader(sr))
{
    while (!sr.EndOfStream)
    {
        o = serializer.Deserialize<List<MyObject>>(reader);
    }
}

这将反序列化c#类对象中的json数据,这将解决您的目的。 之后,您可以再次序列化或将其打印为文本或任何文件。

希望有帮助。

答案 1 :(得分:0)

您不需要自定义提取器即可。

最好的解决方案是逐行添加一个json。然后,您可以使用文本提取器并逐行提取。您还可以选择自己的定界符。

REFERENCE ASSEMBLY [Newtonsoft.Json];
REFERENCE ASSEMBLY [Microsoft.Analytics.Samples.Formats];

    @JsonLines= 
        EXTRACT 
            [JsonLine] string
        FROM
            @Full_Path
        USING 
            Extractors.Text(delimiter:'\b', quoting : false);


@ParsedJSONLines = 
    SELECT 
        Microsoft.Analytics.Samples.Formats.Json.JsonFunctions.JsonTuple([JsonLine]) AS JSONLine
    FROM 
        @JsonLines

@AccessToProperties=
    SELECT 
        JSONLine["Property"] AS Property
    FROM 
        @ParsedJSONLines;