UNPKG

@loaders.gl/json

Version:

Framework-independent loader for JSON and streaming JSON formats

97 lines (96 loc) 3 kB
// loaders.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors // @ts-nocheck import ClarinetParser from "../clarinet/clarinet.js"; import JSONPath from "../jsonpath/jsonpath.js"; // JSONParser builds a JSON object using the events emitted by the Clarinet parser export default class JSONParser { parser; result = undefined; previousStates = []; currentState = Object.freeze({ container: [], key: null }); jsonpath = new JSONPath(); constructor(options) { this.reset(); this.parser = new ClarinetParser({ onready: () => { this.jsonpath = new JSONPath(); this.previousStates.length = 0; this.currentState.container.length = 0; }, onopenobject: (name) => { this._openObject({}); if (typeof name !== 'undefined') { this.parser.emit('onkey', name); } }, onkey: (name) => { this.jsonpath.set(name); this.currentState.key = name; }, oncloseobject: () => { this._closeObject(); }, onopenarray: () => { this._openArray(); }, onclosearray: () => { this._closeArray(); }, onvalue: (value) => { this._pushOrSet(value); }, onerror: (error) => { throw error; }, onend: () => { this.result = this.currentState.container.pop(); }, ...options }); } reset() { this.result = undefined; this.previousStates = []; this.currentState = Object.freeze({ container: [], key: null }); this.jsonpath = new JSONPath(); } write(chunk) { this.parser.write(chunk); } close() { this.parser.close(); } // PRIVATE METHODS _pushOrSet(value) { const { container, key } = this.currentState; if (key !== null) { container[key] = value; this.currentState.key = null; } else { container.push(value); } } _openArray(newContainer = []) { this.jsonpath.push(null); this._pushOrSet(newContainer); this.previousStates.push(this.currentState); this.currentState = { container: newContainer, isArray: true, key: null }; } _closeArray() { this.jsonpath.pop(); this.currentState = this.previousStates.pop(); } _openObject(newContainer = {}) { this.jsonpath.push(null); this._pushOrSet(newContainer); this.previousStates.push(this.currentState); this.currentState = { container: newContainer, isArray: false, key: null }; } _closeObject() { this.jsonpath.pop(); this.currentState = this.previousStates.pop(); } }