Created
July 9, 2019 06:58
-
-
Save danield137/229139b0a7431ca4f15bcb79622b17ee to your computer and use it in GitHub Desktop.
Javascript partial json parsing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Clarinet from 'clarinet'; | |
| class TrackingObject { | |
| data: { [key: string]: any } | null = null; | |
| path: string = ''; | |
| depth: number = 0; | |
| stack: StackItem[] = []; | |
| expandArray(key: string) { | |
| this.stack.push({ type: 'Array', key, value: null }); | |
| } | |
| expandObject(key: string | null) { | |
| this.stack.push({ type: 'Object', key, value: null }); | |
| } | |
| pushValue(key: string | null, value: any) { | |
| if (key === null) { | |
| this.stack.push({ type: 'Value', key, value }); | |
| } else { | |
| this.stack.push({ type: 'KeyValue', key, value }); | |
| } | |
| } | |
| foldArray(key: string | null) { | |
| const agg = []; | |
| let current: StackItem | undefined = this.stack.pop(); | |
| while (current !== undefined && current.type !== 'Array') { | |
| agg.push(current.value); | |
| current = this.stack.pop(); | |
| } | |
| if (current !== undefined && key == null) { | |
| key = current.key; | |
| } | |
| if (this.isClosed()) { | |
| // reverse due to working with stack | |
| this.data = agg.reverse(); | |
| } else { | |
| this.pushValue(key, agg.reverse()); | |
| } | |
| } | |
| foldObject(key: string | null) { | |
| const agg: { [key: string]: any } = {}; | |
| let current: StackItem | undefined = this.stack.pop(); | |
| while (current !== undefined && current.type !== 'Object') { | |
| let k: string = current!.key!; | |
| agg[k] = current.value; | |
| current = this.stack.pop(); | |
| } | |
| if (current !== undefined && key == null) { | |
| key = current.key; | |
| } | |
| if (this.isClosed()) { | |
| this.data = agg; | |
| } else { | |
| this.pushValue(key, agg); | |
| } | |
| } | |
| isClosed(): Boolean { | |
| return this.stack.length === 0; | |
| } | |
| } | |
| // Usage with clarient to build partial objects | |
| export async function extractItemsFromPartialJson(partial: string): Promise<object[]> { | |
| return new Promise<object[]>((resolve, reject) => { | |
| let parser = Clarinet.parser(); | |
| let items: object[] | null = []; | |
| let currentObj: TrackingObject | null = null; | |
| let currentKey: string | null = null; | |
| parser.onvalue = (v: any) => { | |
| currentObj!.pushValue(currentKey!, v); | |
| currentKey = null; | |
| }; | |
| parser.onopenobject = (key: string) => { | |
| if (currentObj === null) { | |
| currentObj = new TrackingObject(); | |
| } | |
| currentObj.expandObject(currentKey); | |
| currentKey = key; | |
| }; | |
| parser.onkey = (key: string) => { | |
| currentKey = key; | |
| }; | |
| parser.oncloseobject = () => { | |
| currentObj!.foldObject(currentKey!); | |
| if (currentObj!.isClosed()) { | |
| items!.push(currentObj!.data!); | |
| currentObj = null; | |
| currentKey = null; | |
| } | |
| }; | |
| parser.onopenarray = () => { | |
| if (currentObj !== null) { | |
| currentObj!.expandArray(currentKey!); | |
| currentKey = null; | |
| } | |
| }; | |
| parser.onclosearray = () => { | |
| if (currentObj !== null) { | |
| currentObj!.foldArray(currentKey!); | |
| currentKey = null; | |
| } | |
| }; | |
| parser.onend = () => { | |
| resolve(items || []); | |
| }; | |
| parser.write(partial).close(); | |
| }); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment