Я получаю данные из 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? или они , действительно в стриме?
Они не разделены запятыми, они выглядят как строки json, за которыми следует другая, как я показал. Я не знаю, как они разграничены, так как приходят из другого приложения. Единственная информация, которую я знаю, это то, что он отправляет поток данных. Я изменил вывод, удалив запятые



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Отредактировано
Для обработки потоковых данных 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).
Извините за путаницу, я обновил решение для эффективной обработки и анализа данных JSON по частям.
Ваше здоровье! Очень ценю
Даже если приложение отправляет фрагменты, каждый из которых состоит ровно из одной строки 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.
Если разделение не сработало, приведите пример того, где оно пошло не так. Разрыв строки в строке JSON никогда не может быть разделенной позицией, если только он не находится между } и {.
Если они всегда разделены запятыми, можно ли обернуть строку в символы
[]... тогда вы могли бы просто запуститьJSON.parse?