在Spark Streaming中解析复杂的字符串

时间:2018-11-07 01:37:57

标签: json apache-spark spark-streaming jsonparser

我从Azure事件中心获取流数据集。数据采用以下格式:

[
  [
    {
      "data": "sampledata1",
      "addressdata": {
        "isTest": false,
        "address": "washington",
        "zipcode": 98119,
        "city": "seattle",
        "randomstring": "abcdabcd:ghkjnkasd:asdasdasd"
      },
      "profession": "engineer",
      "party": "democrat"
    },
    {
      "data": "sampledata2",
      "addressdata": {
        "isTest": false,
        "address": "virginia",
        "zipcode": 20120,
        "city": "Centreville",
        "randomstring": "zabcdabcd:tghkjnkasd:gasdasdasd"
      },
      "profession": "teacher",
      "party": "republican"
    }
  ]
]

从下面的文章中,我可以将json作为原始字符串获取。 https://docs.databricks.com/spark/latest/structured-streaming/streaming-event-hubs.html

但是我无法使用get_jon_object从字符串中提取单个项。我相信问题在于字符串不是单个json对象,而是json数组的数组。因此, get_json_object 无法对其进行解析。

val outputDf = streamingInputDf.select(
     get_json_object(($"body").cast("string"), "$.data").alias("data"), 
     get_json_object(($"body").cast("string"), "$.addressdata").alias("addressdata"), 
     get_json_object(($"body").cast("string"), "$.profession").alias("profession"), 
     get_json_object(($"body").cast("string"), "$.party").alias("party"), 
     date_format($"enqueuedTime", "dd.MM.yyyy").alias("day"),
     date_format($"enqueuedTime", "HH").cast("int").alias("hour") ,
     when(date_format($"enqueuedTime", "mm").cast("int")<=15,1)
    .when(date_format($"enqueuedTime", "mm").cast("int")>15 && date_format($"enqueuedTime", "mm").cast("int")<=30,2)
    .when(date_format($"enqueuedTime", "mm").cast("int")>30 && date_format($"enqueuedTime", "mm").cast("int")<=45,3)
    .otherwise(4).alias("minute")
)   

任何人都有建议,如何优雅地解析数据并从字符串中提取单个信息?有什么类似于get_json_object的方法可以从json数组中提取数据吗?

PS:我在一行中得到了json数组。不像上面提到的。

1 个答案:

答案 0 :(得分:0)

要使用Json类型的格式,有很多工具可以在Java中使用。但是根据我在不同平台上的经验,从性能和准确性等不同方面来看,Google Gson确实是最好的。 (Gson库:https://github.com/google/gson

此外,它真的很容易使用,如以下示例代码所示:

String json = {"insurance1":45.1,"insurance2":505.5};
Gson gson = new Gson();
Map<String, Float> jsonObj = gson.fromJson(json, Map.class);
System.out.println(jsonObj.get("insurance1"));

此外,如果需要更复杂和自定义的数据结构,则可以创建一个Entity并在fromJson方法中使用它,而不是上面的示例中的Map类。作为样本Json,如果存在这些复杂对象的数组或列表,则可以使用TypeToken定义输入Json结构,并在fromJson方法中使用它,例如以下样本格式:

new TypeToken<ArrayList<Class.forName(MyClass)>>

有关TypeToken的更多信息,可以使用此链接: TypeToken