Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

1K
Views
¿Cómo dividir un archivo JSON grande en función de una propiedad de matriz que está profundamente anidada?

Tengo un archivo json grande (alrededor de 16 Gb) con la siguiente estructura:

 { "Job": { "Keys": { "JobID": "test123", "DeviceID": "TEST01" }, "Props": { "FileType": "Measurements", "InstrumentDescriptions": [ { "InstrumentID": "1723007", "InstrumentType": "Actual1", "Name": "U", "DataType": "Double", "Units": "degC" }, { "InstrumentID": "2424009", "InstrumentType": "Actual2", "Name": "VG03", "DataType": "Double", "Units": "Pa" } ] }, "Steps": [ { "Keys": { "StepID": "START", "StepResult": "NormalEnd" }, "InstrumentData": [ { "Keys": { "InstrumentID": "1723007" }, "Measurements": [ { "DateTime": "2021-11-16 21:18:37.000", "Value": 540 }, { "DateTime": "2021-11-16 21:18:37.100", "Value": 539 }, { "DateTime": "2021-11-16 21:18:37.200", "Value": 540 }, { "DateTime": "2021-11-16 21:18:37.300", "Value": 540 }, { "DateTime": "2021-11-16 21:18:37.400", "Value": 540 }, { "DateTime": "2021-11-16 21:18:37.500", "Value": 540 }, { "DateTime": "2021-11-16 21:18:37.600", "Value": 540 }, { "DateTime": "2021-11-16 21:18:37.700", "Value": 538 }, { "DateTime": "2021-11-16 21:18:37.800", "Value": 540 } ] }, { "Keys": { "InstrumentID": "2424009" }, "Measurements": [ { "DateTime": "2021-11-16 21:18:37.000", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.100", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.200", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.300", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.400", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.500", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.600", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.700", "Value": 1333.22 }, { "DateTime": "2021-11-16 21:18:37.800", "Value": 1333.22 } ] } ] } ] } }

El problema

Me gustaría dividir este archivo en varios archivos dividiendo la matriz "InstrumentData" porque esta matriz contendrá la mayor parte de los datos. Dividir este archivo en archivos más pequeños me permitiría analizar el archivo sin obtener una excepción de falta de memoria.

Estado actual

 public static void SplitJson(string filename, string arrayPropertyName) { string templateFileName = @"C:\Temp\template.json"; string arrayFileName = @"C:\Temp\array.json"; CreateEmptyFile(templateFileName); CreateEmptyFile(arrayFileName); using (Stream stream = File.OpenRead(filename)) using (JsonReader reader = new JsonTextReader(new StreamReader(stream))) using (JsonWriter templateWriter = new JsonTextWriter(new StreamWriter(templateFileName))) using (JsonWriter arrayWriter = new JsonTextWriter(new StreamWriter(arrayFileName))) { if (reader.Read() && reader.TokenType == JsonToken.StartObject) { templateWriter.WriteStartObject(); while (reader.Read() && reader.TokenType != JsonToken.EndObject) { string propertyName = (string)reader.Value; reader.Read(); templateWriter.WritePropertyName(propertyName); if (propertyName == arrayPropertyName) { arrayWriter.WriteToken(reader); templateWriter.WriteStartObject(); // empty placeholder object templateWriter.WriteEndObject(); } else if (reader.TokenType == JsonToken.StartObject || reader.TokenType == JsonToken.StartArray) { templateWriter.WriteToken(reader); } else { templateWriter.WriteValue(reader.Value); } } templateWriter.WriteEndObject(); } } // Now read the huge array file and combine each item in the array // with the template to make new files JObject template = JObject.Parse(File.ReadAllText(templateFileName)); using (JsonReader arrayReader = new JsonTextReader(new StreamReader(arrayFileName))) { int counter = 0; while (arrayReader.Read()) { if (arrayReader.TokenType == JsonToken.StartObject) { counter++; JObject item = JObject.Load(arrayReader); template[arrayPropertyName] = item; string fileName = string.Format(@"C:\Temp\output_{0}_{1}_{2}.json", template["name"], template["age"], counter); File.WriteAllText(fileName, template.ToString()); } } } // Clean up temporary files File.Delete(templateFileName); File.Delete(arrayFileName); }

Estoy usando este método para intentar dividir el archivo en archivos más pequeños. Sin embargo, este método solo puede dividir los archivos según las propiedades que se encuentran en el nivel raíz.

La pregunta

¿Estoy en el camino correcto para abordar este problema? ¿Es esta una manera eficiente de abordar esto? ¿Cómo divido el JSON en varios archivos dividiendo la matriz de manera eficiente? El archivo JSON debe dividirse de manera que haya un archivo para cada uno de los elementos en la matriz "InstrumentData". Todas las demás propiedades y estructuras deben conservarse en los archivos divididos.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Esta es una solución un poco fea y no pretende ser la mejor en absoluto, pero permite dividir un json con una estructura similar de varios GB de tamaño en archivos más pequeños que contienen miembros individuales de la matriz línea por línea. Conserva la sangría redundante original y las comas de finalización, pero se pueden corregir adicionalmente si es necesario.

 using var inputStream = File.OpenText("./input.json"); // Searching for the beginning of the array by the "InstrumentData" key string? line; while ((line = inputStream.ReadLine()) != null) { if (line.Contains("\"InstrumentData\"")) break; } // End of file reached, exiting if (line == null) return; // Reading and splitting the "InstrumentData" array. StreamWriter? outputFile = null; var outputFilesCounter = 0; var arrayLevel = 0; var objectLevel = 0; try { while ((line = inputStream.ReadLine()) != null) { // Track the levels of nesting within the array arrayLevel += line.Count(c => c == '['); objectLevel += line.Count(c => c == '{'); // Write a line into the currently opened output file stream if (objectLevel > 0) { outputFile ??= File.CreateText($"./output_{outputFilesCounter++}.json"); outputFile.WriteLine(line); } arrayLevel -= line.Count(c => c == ']'); objectLevel -= line.Count(c => c == '}'); // End of an array member, flush the file stream if (objectLevel == 0) { outputFile?.Dispose(); outputFile = null; } // End of array reached, exiting if (arrayLevel < 0) { outputFile?.Dispose(); return; } } } finally { outputFile?.Dispose(); }
over 4 years ago · Santiago Trujillo Report

0

Aquí hay otro enfoque que puede usar para dividir su archivo Json grande usando Cinchoo ETL , una biblioteca de código abierto

Supone que el archivo json de entrada viene con Job.Steps[*].InstrumentData[*] , que requiere 2 niveles de análisis para dividir los archivos por InstrumentData

Primero, divida el archivo de entrada por cada nodo Steps[*] (también conocido como StepsFiles), luego tome cada StepsFiles y divídalos por cada nodo InstrumentData[*] .

Debido a la complejidad del código, se redactó un violín de muestra para su revisión.

Ejemplo de violín: https://dotnetfiddle.net/j3Y03m

over 4 years ago · Santiago Trujillo Report

0

Mi solución aquí: https://dotnetfiddle.net/CufM4w

La idea es procesar el documento en dos rondas utilizando un autómata de estado relativamente simple.

  1. Extraiga la raíz y las plantillas de cada paso (prefijo y sufijo), pero omita por completo InstrumentData.

  2. Por el contrario, omita todo excepto InstrumentData y use las partes del n. ° 1 para crear una salida.

Entonces, el código principal se verá así (consulte el enlace de arriba para ver la fuente completa):

 var reader = new StringReader(JsonText); var splitter = DataSplitter.Create(reader); reader = new StringReader(JsonText); splitter.Split(reader, (step, index, content) => { Console.WriteLine("=== step: {0}, index: {1} ===", step, index); Console.WriteLine(content); });

Espero haber ayudado.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!