Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

1K
Vistas
¿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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda