JSON-populate
Tool for populating JSON data with infinitely recursive circular references. Sort of like Falcor, but for plain JSON. It uses Proxy
to lazily resolve relations where supported, otherwise there's a polyfill that uses an eager Object.assign
approach (slow and very memory intensive if you populate more than a few levels - it's really just there for symbolic backwards compatibility)
Usage examples
Populating by naming convention:
/** * Import lib */const populateByConvention = ; /** * Example data */const stories = type: 'story' id: 'story-1' author: person: 'person-1' type: 'story' id: 'story-2' author: person: 'person-2' ; const people = type: 'person' id: 'person-1' name: 'John Storywriter' authored: stories: 'story-1' likes: stories: 'story-1' 'story-2' type: 'person' id: 'person-2' name: 'Peter Telltale' authored: stories: 'story-2' likes: stories: 'story-1' 'story-2' ; /** * Consolidate the collections into a "graph" */const graph = people stories ; /** * Choose an entry point to the graph */const entry = people0; /** * Create a populated entry point resolved against the graph with a specified depth */const populatedItem = ; /** * Result */console; /** * { * "type": "person", * "id": "person-1", * "name": "John Storywriter", * "authored": { * "stories": [ * { * "type": "story", * "id": "story-1", * "author": { * "person": { * "type": "person", * "id": "person-1", * "name": "John Storywriter", * "authored": { * "stories": [ * "story-1" * ] * }, * "likes": { * "stories": [ * "story-1", * "story-2" * ] * } * } * } * } * ] * }, * "likes": { * "stories": [ * { * "type": "story", * "id": "story-1", * "author": { * "person": { * "type": "person", * "id": "person-1", * "name": "John Storywriter", * "authored": { * "stories": [ * "story-1" * ] * }, * "likes": { * "stories": [ * "story-1", * "story-2" * ] * } * } * } * }, * { * "type": "story", * "id": "story-2", * "author": { * "person": { * "type": "person", * "id": "person-2", * "name": "Peter Telltale", * "authored": { * "stories": [ * "story-2" * ] * }, * "likes": { * "stories": [ * "story-1", * "story-2" * ] * } * } * } * } * ] * } * } */
Populating by explicit reference:
/** * Import lib */const populateByReference = ; /** * Example data */const stories = type: 'story' id: 'story-1' author: $ref: 'people' id: 'person-1' type: 'story' id: 'story-2' author: $ref: 'people' id: 'person-2' ; const people = type: 'person' id: 'person-1' name: 'John Storywriter' authored: $ref: 'stories' id: 'story-1' likes: $ref: 'stories' id: 'story-1' $ref: 'stories' id: 'story-2' type: 'person' id: 'person-2' name: 'Peter Telltale' authored: $ref: 'stories' id: 'story-2' likes: $ref: 'stories' id: 'story-1' $ref: 'stories' id: 'story-2' ; /** * Consolidate the collections into a "graph" */const graph = people stories ; /** * Choose an entry point to the graph */const entry = people0; /** * Create a populated entry point resolved against the graph with a specified depth */const populatedItem = ; /** * Result */console; /** * { * "type": "person", * "id": "person-1", * "name": "John Storywriter", * "authored": [ * { * "type": "story", * "id": "story-1", * "author": { * "type": "person", * "id": "person-1", * "name": "John Storywriter", * "authored": [ * { * "$ref": "stories", * "id": "story-1" * } * ], * "likes": [ * { * "$ref": "stories", * "id": "story-1" * }, * { * "$ref": "stories", * "id": "story-2" * } * ] * } * } * ], * "likes": [ * { * "type": "story", * "id": "story-1", * "author": { * "type": "person", * "id": "person-1", * "name": "John Storywriter", * "authored": [ * { * "$ref": "stories", * "id": "story-1" * } * ], * "likes": [ * { * "$ref": "stories", * "id": "story-1" * }, * { * "$ref": "stories", * "id": "story-2" * } * ] * } * }, * { * "type": "story", * "id": "story-2", * "author": { * "type": "person", * "id": "person-2", * "name": "Peter Telltale", * "authored": [ * { * "$ref": "stories", * "id": "story-2" * } * ], * "likes": [ * { * "$ref": "stories", * "id": "story-1" * }, * { * "$ref": "stories", * "id": "story-2" * } * ] * } * } * ] * } */