Разбор вложенного JSON с помощью SCALA

Я хочу ввести данные телеметрии, и на выходе будет многоуровневый вложенный файл JSON. Меня интересуют очень конкретные поля, но я не могу проанализировать файл JSON, чтобы получить данные.

Образец данных:

{ "version_str": "1.0.0", "node_id_str": "router-01", "encoding_path": "sys/intf", "collection_id": 241466, "collection_start_time": 0, "collection_end_time": 0, "msg_timestamp": 0, "subscription_id": [ ], "sensor_group_id": [ ], "data_source": "DME", "data": { "interfaceEntity": { "attributes": { "childAction": "", "descr": "", "dn": "sys/intf", "modTs": "2017-09-19T13:24:14.751+00:00", "monPolDn": "uni/fabric/monfab-default", "persistentOnReload": "true", "status": "" }, "children": [ { "l3LbRtdIf": { "attributes": { "adminSt": "up", "childAction": "", "descr": "Nothing", "id": "lo103", "linkLog": "default", "modTs": "2017-11-06T23:18:02.974+00:00", "monPolDn": "uni/fabric/monfab-default", "name": "", "persistentOnReload": "true", "rn": "lb-[lo103]", "status": "", "uid": "0" }, "children": [ { "ethpmLbRtdIf": { "attributes": { "currErrIndex": "4294967295", "ifIndex": "335544423", "iod": "14", "lastErrors": "0,0,0,0", "operBitset": "", "operDescr": "Nothing", "operMtu": "1500", "operSt": "up", "operStQual": "none", "rn": "lbrtdif" } } }, { "nwRtVrfMbr": { "attributes": { "childAction": "", "l3vmCfgFailedBmp": "", "l3vmCfgFailedTs": "00:00:00:00.000", "l3vmCfgState": "0", "modTs": "2017-11-06T23:18:02.945+00:00", "monPolDn": "", "parentSKey": "unspecified", "persistentOnReload": "true", "rn": "rtvrfMbr", "status": "", "tCl": "l3Inst", "tDn": "sys/inst-default", "tSKey": "" } } } ] } }, { "l3LbRtdIf": { "attributes": { "adminSt": "up", "childAction": "", "descr": "Nothing", "id": "lo104", "linkLog": "default", "modTs": "2018-01-25T15:54:20.367+00:00", "monPolDn": "uni/fabric/monfab-default", "name": "", "persistentOnReload": "true", "rn": "lb-[lo104]", "status": "", "uid": "0" }, "children": [ { "ethpmLbRtdIf": { "attributes": { "currErrIndex": "4294967295", "ifIndex": "335544424", "iod": "77", "lastErrors": "0,0,0,0", "operBitset": "", "operDescr": "Nothing", "operMtu": "1500", "operSt": "up", "operStQual": "none", "rn": "lbrtdif" } } }, { "nwRtVrfMbr": { "attributes": { "childAction": "", "l3vmCfgFailedBmp": "", "l3vmCfgFailedTs": "00:00:00:00.000", "l3vmCfgState": "0", "modTs": "2018-01-25T15:53:55.757+00:00", "monPolDn": "", "parentSKey": "unspecified", "persistentOnReload": "true", "rn": "rtvrfMbr", "status": "", "tCl": "l3Inst", "tDn": "sys/inst-default", "tSKey": "" } } } ] } }, { "l3LbRtdIf": { "attributes": { "adminSt": "up", "childAction": "", "descr": "Nothing", "id": "lo101", "linkLog": "default", "modTs": "2017-11-13T21:39:58.910+00:00", "monPolDn": "uni/fabric/monfab-default", "name": "", "persistentOnReload": "true", "rn": "lb-[lo101]", "status": "", "uid": "0" }, "children": [ { "ethpmLbRtdIf": { "attributes": { "currErrIndex": "4294967295", "ifIndex": "335544421", "iod": "12", "lastErrors": "0,0,0,0", "operBitset": "", "operDescr": "Nothing", "operMtu": "1500", "operSt": "up", "operStQual": "none", "rn": "lbrtdif" } } }, { "nwRtVrfMbr": { "attributes": { "childAction": "", "l3vmCfgFailedBmp": "", "l3vmCfgFailedTs": "00:00:00:00.000", "l3vmCfgState": "0", "modTs": "2017-11-13T21:39:58.880+00:00", "monPolDn": "", "parentSKey": "unspecified", "persistentOnReload": "true", "rn": "rtvrfMbr", "status": "", "tCl": "l3Inst", "tDn": "sys/inst-default", "tSKey": "" } } } ] } }, { "l3LbRtdIf": { "attributes": { "adminSt": "up", "childAction": "", "descr": "\"^:tier2:if:loopback:mgmt:l3\"", "id": "lo0", "linkLog": "default", "modTs": "2017-09-25T20:29:54.003+00:00", "monPolDn": "uni/fabric/monfab-default", "name": "", "persistentOnReload": "true", "rn": "lb-[lo0]", "status": "", "uid": "0" }, "children": [ { "ethpmLbRtdIf": { "attributes": { "currErrIndex": "4294967295", "ifIndex": "335544320", "iod": "11", "lastErrors": "0,0,0,0", "operBitset": "", "operDescr": "\"^:tier2:if:loopback:mgmt:l3\"", "operMtu": "1500", "operSt": "up", "operStQual": "none", "rn": "lbrtdif" } } }, { "nwRtVrfMbr":...

Меня интересуют эти атрибуты:

|    |    |    |    |    |    |    |-- rmonIfIn: struct (nullable = true)
|    |    |    |    |    |    |    |    |-- attributes: struct (nullable = true                                                                                        )
|    |    |    |    |    |    |    |    |    |-- broadcastPkts: string (nullabl                                                                                        e = true)
|    |    |    |    |    |    |    |    |    |-- discards: string (nullable = t                                                                                        rue)
|    |    |    |    |    |    |    |    |    |-- errors: string (nullable = tru                                                                                        e)
|    |    |    |    |    |    |    |    |    |-- multicastPkts: string (nullabl                                                                                        e = true)
|    |    |    |    |    |    |    |    |    |-- nUcastPkts: string (nullable =                                                                                         true)
|    |    |    |    |    |    |    |    |    |-- packetRate: string (nullable =                                                                                         true)
import org.apache.spark.sql.SparkSession    
import org.apache.spark.sql.types._
import org.apache.spark.sql.functions.explode
import spark.implicits._

val spark = SparkSession.builder().getOrCreate

val df = spark.read.option("header","true").option("inferSchema","true").json("file:///usr/local/Projects/out.txt")

val mapDF = df.select($"node_id_str" as "nodename", $"data".getItem("InterfaceEntity").getItem("children").getItem("l1PhysIf").getItem("children").getItem("element"))

Я продолжаю получать сообщение об ошибке, когда пытаюсь углубиться, я продолжаю получать ошибку типа данных:

stringJsonDF: org.apache.spark.sql.DataFrame = [nestDevice: string]
org.apache.spark.sql.AnalysisException: cannot resolve '`data`.`InterfaceEntity`.`children`.`l1PhysIf`.`children`['element']' due to data type mismatch: argument 2 requires integral type, however, ''element'' is of string type.;;

Вы должны опубликовать минимальный воспроизводимый пример или хотя бы полную схему.

zero323 25.04.2018 18:08

Есть ли способ прикрепить документ?

user3521305 25.04.2018 18:09

Нет, вы должны использовать блоки кода.

zero323 25.04.2018 18:10

@ user3521305 был ли мой ответ о какой-либо помощи? Если нет, пожалуйста, оставьте отзыв, в противном случае вы можете принять его?

Tom Lous 02.05.2018 09:35
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
2
4
2 342
2

Ответы 2

Вы можете использовать библиотеку Google Gson, которая используется для работы с json. Вы можете преобразовать любой объект в json и, конечно, сделать это в обратном порядке. вот пример для этого:

Gson gson = new Gson();
List<Map<Long, String>> listOfMaps = new ArrayList<>();
//here you can new some maps and add them to the listOfMaps. 
String listOfMapsInJsonFormat = gson.toJson(listOfMaps);

приведенный выше пример кода предназначен для преобразования объекта в json. Чтобы выполнить обратную работу, вы также можете проверить один ниже:

Gson gson = new Gson();
List list = gson.fromJson(listOfMapsInJsonFormat, List.class);

приведенный выше код изменит вашу входную строку json на список, содержащий карты. Конечно, может быть разница в типе карты, которая у вас была до преобразования исходного объекта в json, и тот, который gson строит объект из строки json. чтобы избежать этого, вы можете использовать класс TypeToken:

Gson gson = new Gson();
Type type = new TypeToken()<ArrayList<Map<>>>{}.getType();
ArrayList<Map<>> = gson.fromJson(listOfMapsInJsonFormat, type);

Эти данные, с которыми я работаю, уже имеют формат json. Моя проблема - это возможность получить данные, расположенные на нескольких уровнях.

user3521305 25.04.2018 19:45

просто продолжайте читать до конца моего ответа. Я только что описал, как gson помогает конвертировать из json в объект (десериализация) и даже в обратном направлении (сериализация). вы можете сделать что-то вроде второго примера кода: gson.fromJson (jsonString, Map.class). затем выполните итерацию по карте, чтобы найти данные, которые вы хотите извлечь.

Amin Heydari Alashti 25.04.2018 19:49

Поскольку поля являются частью нескольких вложенных массивов, логика предполагает, что вас интересуют все итерации этих полей для каждой записи (так что, если одна запись содержит элементы пrmonIfIn из-за вложенных массивов, вам будет интересен каждый из них?)

Если это так, имеет смысл explode использовать эти вложенные массивы и обрабатывать расширенный фрейм данных.

Основываясь на вашем коде и неполном примере json, это может выглядеть примерно так:

val nested = df
  .select(explode($"data.InterfaceEntity").alias("l1"))
  .select(explode($"l1.l1PhysIf").alias("l2"))
  .select($"l2.rmonIfIn.attributes".alias("l3"))
  .select($"l3.broadcastPkts", $"l3.discards", $"l3.errors", $"l3.multicastPkts", $"l3.packetRate")

Возврат фрейма данных, который мог бы выглядеть как

+-------------+--------+------+-------------+----------+
|broadcastPkts|discards|errors|multicastPkts|packetRate|
+-------------+--------+------+-------------+----------+
|1            |1       |1     |1            |1         |
|2            |2       |2     |2            |2         |
|3            |3       |3     |3            |3         |
|4            |4       |4     |4            |4         |
+-------------+--------+------+-------------+----------+

Другие вопросы по теме