Разбор вложенного JSON с использованием SCALA - PullRequest
0 голосов
/ 25 апреля 2018

Я хочу ввести данные телеметрии, и на выходе получается многослойный вложенный файл 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": {"attribute": {"childAction": "", "descr": "", "dn": "sys / intf", "modTs": "2017-09-19T13: 24: 14.751 + 00: 00", "monPolDn": "uni / fabric / monfab-default", "persistentOnReload": "true", "status": ""}, "children": [{"l3LbRtdIf": {"attribute": { "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": {"attribute": {"currErrIndex": "4294967295", "ifIndex": "335544423", "iod": "14", "lastErrors": "0,0,0,0", "operBitset": "", "operDescr": "Nothing", "operMtu": "1500", "operSt": "up", "operStQual": "none", "rn": "lbrtdif"}}}, { "nwRtVrfMbr": {"attribute": {"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": {"attribute": {"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": {"attribute": { "currErrIndex": "4294967295", "ifIndex": "335544424", "iod": "77", "lastErrors": "0,0,0,0", "operBitset": "", "operDescr": "Nothing", "operMtu": "1500", "operSt": "up", "operStQual": "none", "rn": "lbrtdif"}}}, {"nwRtVrfMbr": {"attribute": { "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": {"attribute": {"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": {"attribute": { "currErrIndex": "4294967295", "ifIndex": "335544421", "iod": "12", "lastErrors": "0,0,0,0", "operBitset": "", "operDescr": "Nothing", "operMtu": "1500", "operSt": "up", "operStQual": "none", "rn": "lbrtdif"}}}, {"nwRtVrfMbr": {"attribute": { "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": {"attribute": {"adminSt": "up", "childAction": "", "descr": "\" ^: tier2: if: loopback: mgmt: l3 \ "", "id": "lo0", "linkLog": "по умолчанию", "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": {"attribute": {"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.;;

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

Поскольку поля являются частью нескольких вложенных массивов, логика предполагает, что вас интересуют все итерации этих полей для каждой записи (поэтому, если одна запись содержит n 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         |
+-------------+--------+------+-------------+----------+
0 голосов
/ 25 апреля 2018

Вы можете использовать библиотеку 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...