| 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 | 6x
6x
6x
1x
5x
52x
52x
10x
42x
2x
2x
1x
1x
6x
6x
1x
5x
7x
7x
2x
5x
6x
6x
6x
13x
6x
6x
6x
6x
20x
20x
6x
6x
6x
6x
6x
6x
6x
14x
7x
7x
7x
7x
7x
7x
7x
7x
2x
2x
2x
2x
2x
2x
2x
7x
7x
2x
2x
2x
2x
2x
5x
1x
1x
1x
1x
4x
6x
11x
11x
11x
11x
6x
| const document = require('../document')
const URL = require('url-parse')
function unescapeKey (key) {
if (key.match(/__(type|meta)$/)) {
return key.substring(1)
}
return key
}
function getString (obj, key) {
const value = obj[key]
if (typeof (value) === 'string') {
return value
}
return ''
}
function getBoolean (obj, key) {
const value = obj[key]
if (typeof (value) === 'boolean') {
return value
}
return false
}
function getObject (obj, key) {
const value = obj[key]
if (typeof (value) === 'object') {
return value
}
return {}
}
function getArray (obj, key) {
const value = obj[key]
if (value instanceof Array) {
return value
}
return []
}
function getContent (data, baseUrl) {
const excluded = ['_type', '_meta']
var content = {}
for (var property in data) {
if (data.hasOwnProperty(property) && !excluded.includes(property)) {
const key = unescapeKey(property)
const value = primitiveToNode(data[property], baseUrl)
content[key] = value
}
}
return content
}
function primitiveToNode (data, baseUrl) {
const isObject = data instanceof Object && !(data instanceof Array)
if (isObject && data._type === 'document') {
// Document
const meta = getObject(data, '_meta')
const relativeUrl = getString(meta, 'url')
const url = relativeUrl ? URL(relativeUrl, baseUrl).toString() : ''
const title = getString(meta, 'title')
const description = getString(meta, 'description')
const content = getContent(data, url)
return new document.Document(url, title, description, content)
} else if (isObject && data._type === 'link') {
// Link
const relativeUrl = getString(data, 'url')
const url = relativeUrl ? URL(relativeUrl, baseUrl).toString() : ''
const method = getString(data, 'action') || 'get'
const title = getString(data, 'title')
const description = getString(data, 'description')
const fieldsData = getArray(data, 'fields')
var fields = []
for (let idx = 0, len = fieldsData.length; idx < len; idx++) {
let value = fieldsData[idx]
let name = getString(value, 'name')
let required = getBoolean(value, 'required')
let location = getString(value, 'location')
let fieldDescription = getString(value, 'fieldDescription')
let field = new document.Field(name, required, location, fieldDescription)
fields.push(field)
}
return new document.Link(url, method, 'application/json', fields, title, description)
} else if (isObject) {
// Object
let content = {}
for (let key in data) {
Eif (data.hasOwnProperty(key)) {
content[key] = primitiveToNode(data[key], baseUrl)
}
}
return content
} else if (data instanceof Array) {
// Object
let content = []
for (let idx = 0, len = data.length; idx < len; idx++) {
content.push(primitiveToNode(data[idx], baseUrl))
}
return content
}
// Primitive
return data
}
class CoreJSONCodec {
constructor () {
this.mediaType = 'application/coreapi+json'
}
decode (text, options = {}) {
let data = text
Eif (options.preloaded === undefined || !options.preloaded) {
data = JSON.parse(text)
}
return primitiveToNode(data, options.url)
}
}
module.exports = {
CoreJSONCodec: CoreJSONCodec
}
|