forked from linkeddata/rdflib.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjsonldparser.js
More file actions
141 lines (119 loc) · 4.33 KB
/
jsonldparser.js
File metadata and controls
141 lines (119 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import {arrayToStatements} from './utils'
/**
* Parses json-ld formatted JS objects to a rdf Term.
* @param kb - The DataFactory to use.
* @param obj - The json-ld object to process.
* @return {Literal|NamedNode|BlankNode|Collection}
*/
export function jsonldObjectToTerm(kb, obj) {
if (typeof obj === 'string') {
return kb.rdfFactory.literal(obj)
}
if (Object.prototype.hasOwnProperty.call(obj, '@list')) {
if (kb.rdfFactory.supports["COLLECTIONS"] === true) {
return listToCollection(kb, obj['@list'])
}
return listToStatements(kb, obj)
}
if (Object.prototype.hasOwnProperty.call(obj, '@id')) {
return nodeType(kb, obj)
}
if (Object.prototype.hasOwnProperty.call(obj, '@language')) {
return kb.rdfFactory.literal(obj['@value'], obj['@language'])
}
if (Object.prototype.hasOwnProperty.call(obj, '@type')) {
return kb.rdfFactory.literal(obj['@value'], kb.rdfFactory.namedNode(obj['@type']))
}
if (Object.prototype.hasOwnProperty.call(obj, '@value')) {
return kb.rdfFactory.literal(obj['@value'])
}
return kb.rdfFactory.literal(obj)
}
/**
* Adds the statements in a json-ld list object to {kb}.
*/
function listToStatements(kb, obj) {
const listId = obj['@id'] ? nodeType(kb, obj) : kb.rdfFactory.blankNode()
const items = obj['@list'].map((listItem => jsonldObjectToTerm(kb, listItem)))
const statements = arrayToStatements(kb.rdfFactory, listId, items)
kb.addAll(statements)
return listId
}
function listToCollection(kb, obj) {
if (!Array.isArray(obj)) {
throw new TypeError("Object must be an array")
}
return kb.rdfFactory.collection(obj.map((o) => jsonldObjectToTerm(kb, o)))
}
/**
* Takes a json-ld formatted string {str} and adds its statements to {kb}.
*
* Ensure that {kb.rdfFactory} is a DataFactory.
*/
export default async function jsonldParser(str, kb, base) {
const baseString = base && Object.prototype.hasOwnProperty.call(base, 'termType')
? base.value
: base
const jsonld = await import('jsonld')
// ⚠ Unit tests also work without accessing `jsonld.default` explicitly, but real browser usage will fail with
// just calling `jsonld.flatten`, so please do not remove `default`
const flattened = await jsonld.default.flatten(JSON.parse(str), null, {base: baseString})
return flattened.reduce((store, flatResource) => processResource(store, base, flatResource), kb)
}
function nodeType(kb, obj) {
if (obj['@id'].startsWith('_:')) {
// This object is a Blank Node. Pass the id without the `_:` prefix
return kb.rdfFactory.blankNode(obj['@id'].substring(2))
} else {
// This object is a Named Node
return kb.rdfFactory.namedNode(obj['@id'])
}
}
function processResource(kb, base, flatResource) {
const id = flatResource['@id']
? nodeType(kb, flatResource)
: kb.rdfFactory.blankNode()
for (const property of Object.keys(flatResource)) {
if (property === '@id') {
continue
} else if (property == '@graph') {
// the JSON-LD flattened structure may contain nested graphs
// the id value for this object is the new base (named graph id) for all nested flat resources
const graphId = id
// this is an array of resources
const nestedFlatResources = flatResource[property]
// recursively process all flat resources in the array, but with the graphId as base.
for (let i = 0; i < nestedFlatResources.length; i++) {
kb = processResource(kb, graphId, nestedFlatResources[i])
}
}
const value = flatResource[property]
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
kb.addStatement(createStatement(kb, id, property, value[i], base))
}
} else {
kb.addStatement(createStatement(kb, id, property, value, base))
}
}
return kb
}
/**
* Create statement quad depending on @type being a type node
* @param kb
* @param subject id
* @param property
* @param value
* @return quad statement
*/
function createStatement(kb, id, property, value, base) {
let predicate, object
if (property === "@type") {
predicate = kb.rdfFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
object = kb.rdfFactory.namedNode(value)
} else {
predicate = kb.rdfFactory.namedNode(property)
object = jsonldObjectToTerm(kb, value)
}
return kb.rdfFactory.quad(id, predicate, object, kb.rdfFactory.namedNode(base))
}