@loaders.gl/json
Version:
Framework-independent loader for JSON and streaming JSON formats
119 lines (95 loc) • 2.72 kB
text/typescript
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
// @ts-nocheck
import ClarinetParser, {ClarinetParserOptions} from '../clarinet/clarinet';
import JSONPath from '../jsonpath/jsonpath';
// JSONParser builds a JSON object using the events emitted by the Clarinet parser
export default class JSONParser {
readonly parser: ClarinetParser;
result = undefined;
previousStates = [];
currentState = Object.freeze({container: [], key: null});
jsonpath: JSONPath = new JSONPath();
constructor(options: ClarinetParserOptions) {
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(): void {
this.result = undefined;
this.previousStates = [];
this.currentState = Object.freeze({container: [], key: null});
this.jsonpath = new JSONPath();
}
write(chunk): void {
this.parser.write(chunk);
}
close(): void {
this.parser.close();
}
// PRIVATE METHODS
_pushOrSet(value): void {
const {container, key} = this.currentState;
if (key !== null) {
container[key] = value;
this.currentState.key = null;
} else {
container.push(value);
}
}
_openArray(newContainer = []): void {
this.jsonpath.push(null);
this._pushOrSet(newContainer);
this.previousStates.push(this.currentState);
this.currentState = {container: newContainer, isArray: true, key: null};
}
_closeArray(): void {
this.jsonpath.pop();
this.currentState = this.previousStates.pop();
}
_openObject(newContainer = {}): void {
this.jsonpath.push(null);
this._pushOrSet(newContainer);
this.previousStates.push(this.currentState);
this.currentState = {container: newContainer, isArray: false, key: null};
}
_closeObject(): void {
this.jsonpath.pop();
this.currentState = this.previousStates.pop();
}
}