U-SQL 使用文本提取器后忽略在 JsonFunctions.JsonTuple() 中导致 JSON 异常的行

U-SQL Ignore rows causing JSON exception in JsonFunctions.JsonTuple() after using Text Extractor

我正在尝试将 JSON 文件转换为 csv,提取一些特定的 key/values 感兴趣的内容。我有大型文本文件(> 100 万行),其中每一行都是一个 JSON 对象。实际结构是嵌套的,包含数组,但对于本题应该不重要。

示例文件:

{"param1": val00, "param2": val01}
{"param1": val10, "param2": val11}
...
{"param1": valn0, "param2": valn1}

我将以下代码与文本提取器一起使用,将每一行转换为一个 JSON 对象,然后使用 JsonFunctions.JsonTuple()[=19= 解析 JSON 对象]

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

USING Microsoft.Analytics.Samples.Formats.Json;

@RawExtract = 
    EXTRACT RawString string
    FROM @InputFile 
    USING Extractors.Text(delimiter:'\b', quoting:false);

@json =
    SELECT JsonFunctions.JsonTuple(RawString, "..*") AS RootObject
    FROM @RawExtract;

我运行陷入问题,因为至少有一行被损坏,如下:

{"param1": val00, "param2"{"param1": val10, "param2": val11}
...
{"param1": valn0, "param2": valn1}

这些是我收到的错误信息

VertexFailedFast: Vertex failed with a fail-fast error E_RUNTIME_USER_EXPRESSIONEVALUATION Error while evaluating expression Microsoft.Analytics.Samples.Formats.Json.JsonFunctions.JsonTuple(RawString, "..*") Inner exception from user expression: After parsing a value an unexpected character was encountered: {.

==== Caught exception Newtonsoft.Json.JsonReaderException at Newtonsoft.Json.JsonTextReader.ParsePostValue(Boolean ignoreComments) at Newtonsoft.Json.JsonTextReader.Read() at Newtonsoft.Json.Linq.JContainer.ReadContentFrom(JsonReader r, JsonLoadSettings settings) at Newtonsoft.Json.Linq.JContainer.ReadTokenFrom(JsonReader reader, JsonLoadSettings options) at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings) at Newtonsoft.Json.Linq.JToken.ReadFrom(JsonReader reader, JsonLoadSettings settings) at Newtonsoft.Json.Linq.JToken.Parse(String json, JsonLoadSettings settings) at Microsoft.Analytics.Samples.Formats.Json.JsonFunctions.JsonTuple[T](String json, String[] paths) at Microsoft.Analytics.Samples.Formats.Json.JsonFunctions.JsonTuple(String json, String[] paths) at _Scope_Generated_Classes_.SqlFilterTransformer_13.Process(IRow inRow, IUpdatableRow outRow) in d:\data\yarnnm\local\usercache905a29-60cf-4dd2-bf9c-c2b31bedea60\appcache\application_1546207842059_5159256\container_e346_1546207842059_5159256_01_000001\wd__ScopeCodeGen__.dll.cs:line 233

我不介意少写几行。我看到对于提取器,我可以使用 silent: true 来忽略坏行。 JsonFunctions.JsonTuple() 解析函数是否有类似的选项?

JsonTuple 没有类似的选项。

我看到有 2 个选项可以解决这个问题。

  1. 创建隐藏代码以捕获错误
  2. 编写您自己的 JsonFunctions 版本来处理错误。

源代码在这里: https://github.com/Azure/usql/blob/master/Examples/DataFormats/Microsoft.Analytics.Samples.Formats/Json/JsonFunctions.cs

可以在 U-SQL 脚本中创建一个 try-catch 块以避免在 JsonReaderException 上崩溃。

Try-catch 块

// Ignore rows with invalid JSON formattting
DECLARE @TryParseJson Func<string, SqlMap<string, string>> = (RawString)=>{
    try 
    {
        return JsonFunctions.JsonTuple(RawString, "..*");
    }
    catch (Newtonsoft.Json.JsonReaderException e)
    {
        return null;  // Consider returning empty SqlMap<string, string> instead
    }
};

提取并解析JSON

每行包含一个 JSON 字符串

@RawExtract = 
    EXTRACT RawString string
    FROM @InputFile 
    USING Extractors.Text(delimiter:'\b', quoting:false);

@json =
    SELECT @TryParseJson(RawString) AS RootObject
    FROM @RawExtract;

忽略具有无效 JSON(空值)的行

@result =
    SELECT RootObject["id"] AS Id
         , RootObject["status"] AS Status
         , RootObject["time"] AS Time
    FROM @json
    WHERE RootObject != null;  // Ignore invalid JSON