Как разделить фрагменты на отдельные объекты JSON

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

         { 
           "productName": "bag",
           "code": "BGX-112"
         } 
         { 
           "productName": "purse",
           "code": "PUSR-112"
         } 
         etc..


Вот код, который обрабатывает данные:


            const getProductData = async (url:string) => {
               const decoder = new TextDecoderStream()
               let chunks: any[];
               chunks = [];
               try {
                   const response = await fetch(url)
                   const stream = response?.body.pipeThrough(new TextDecoderStream());
                   const reader = stream.getReader()
                   while (true) {
                       const {value, done} = await reader.read();
                       if (done) {
                           // Flush any buffered characters.
                           const stringArray = value?.split(/\b\s/);
                           chunks.push(value);
                           return chunks;
                       }
                       if (value) {
                           const stringArray = value?.split(/\b\s/);
                           chunks.push(value);
                       }
        
                   }
               }catch (e) {
                   console.error("Error ",e)
               }
           }



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

Если они всегда разделены запятыми, можно ли обернуть строку в символы []... тогда вы могли бы просто запустить JSON.parse?

freefaller 22.08.2024 09:13

действительно ли это так? нет [ в начале? является ли каждый фрагмент самостоятельной действительной строкой JSON? или они , действительно в стриме?

Jaromanda X 22.08.2024 09:13

Они не разделены запятыми, они выглядят как строки json, за которыми следует другая, как я показал. Я не знаю, как они разграничены, так как приходят из другого приложения. Единственная информация, которую я знаю, это то, что он отправляет поток данных. Я изменил вывод, удалив запятые

BreenDeen 22.08.2024 14:26
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Отредактировано

Для обработки потоковых данных JSON используйте TextDecoder для объединения фрагментов в строку. Найдите разделители (например, }\n{), чтобы идентифицировать полные объекты JSON. Разделите строку в этих точках и проанализируйте каждый сегмент с помощью JSON.parse().

Серверная сторона:

const express = require('express');
const app = express();
const port = 3000;

app.get('/large-json', (req, res) => {
    res.setHeader('Content-Type', 'application/json');

    for (let i = 0; i < 1000; i++) {
        const jsonObject = JSON.stringify({ productName: `item${i}`, code: `CODE-${i}` });
        res.write(jsonObject + '\n');  // Separate objects with a newline
    }

    res.end();
});

app.listen(port, () => {
    console.info(`Server running at http://localhost:${port}/`);
});

Клиентская сторона:

const getProductData = async (url: string) => {
    try {
        const response = await fetch(url);
        const reader = response.body?.getReader();

        let decoder = new TextDecoder();
        let partialData = '';

        if (!reader) throw new Error("Stream reader not available");

        while (true) {
            const { value, done } = await reader.read();
            if (done) break;

            partialData += decoder.decode(value, { stream: true });

            let lines = partialData.split('\n');
            partialData = lines.pop()||'';  

            for (let line of lines) {
                if (line.trim()) {
                    try {
                        const jsonObject = JSON.parse(line);
                        console.info(jsonObject);
                    } catch (e) {
                        console.error("JSON parsing error: ", e);
                    }
                }
            }
        }

        if (partialData.trim()) {
            try {
                const jsonObject = JSON.parse(partialData);
                console.info(jsonObject);
            } catch (e) {
                console.error("JSON parsing error in final chunk: ", e);
            }
        }
    } catch (e) {
        console.error("Error ", e);
    }
};
getProductData("http://localhost:3000/large-json");

Мне не нужны все данные, поскольку данные могут составлять мегабайты данных. Когда данные json станут доступными, я хочу проанализировать их как объекты json и добавить в фрагменты, чтобы можно было отображать их в фрагментах данных json, иначе у меня закончится память. Я также получаю сообщение об ошибке SyntaxError: Ожидаемое имя свойства или «}» в JSON в позиции 1 (строка 1, столбец 2).

BreenDeen 22.08.2024 14:24

Извините за путаницу, я обновил решение для эффективной обработки и анализа данных JSON по частям.

Ammar yasser 22.08.2024 16:20

Ваше здоровье! Очень ценю

BreenDeen 22.08.2024 17:14

Даже если приложение отправляет фрагменты, каждый из которых состоит ровно из одной строки JSON, stream, выходящий из текстового декодера, может объединить несколько отправленных фрагментов в один фрагмент, видимый reader.

Если бы строки JSON были огромными, могло бы случиться так, что даже одна из них была бы разделена на два фрагмента, видимых reader. В приведенном ниже решении предполагается, что это не так (другими словами: приложение передает много маленьких строк JSON, а не одну огромную).

При таком предположении код ниже разбивает каждый фрагмент, видимый reader, в тех позициях, где за закрывающей скобкой следует (пробел и) открывающая скобка. Этого достаточно, если каждая строка JSON представляет собой просто объект productName/code, как указано в вашем вопросе. Если строки JSON более сложные, возможно, потребуется адаптировать разделение.

(async function() {
  const reader = (await fetch("https://httpbin.org/stream/10")).body.pipeThrough(new TextDecoderStream()).getReader();
  while (true) {
    const {
      value,
      done
    } = await reader.read();
    console.info("new chunk read, done  = ", done);
    for (const v of value.split(/(?<=\})\s*(?=\{)/))
      console.info(JSON.parse(v).id);
    if (done) return;
  }
})();

10 фрагментов JSON, отправленных приложением, образуют 2 фрагмента (плюс пустой), видимые reader.

Строки составляют около 100 на фрагмент, возвращаемый read(), поэтому я хочу обработать их, добавив 100 объектов json. Вышеупомянутое на самом деле не дало мне ожидаемого количества объектов json, поскольку в большинстве случаев было \n.

BreenDeen 22.08.2024 16:12

Если разделение не сработало, приведите пример того, где оно пошло не так. Разрыв строки в строке JSON никогда не может быть разделенной позицией, если только он не находится между } и {.

Heiko Theißen 22.08.2024 16:43

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