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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
/*-------------------------------------------------------------------------
*
* json.h
* Core JSON manipulation routines used by JSON data type support,
* along with miscellaneous declarations and includes.
*
* Copyright (c) 2010, PostgreSQL Global Development Group
* Written by Joey Adams <[email protected]>.
*
*-------------------------------------------------------------------------
*/
#ifndef JSON_H
#define JSON_H
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
typedef struct varlena jsontype;
#define DatumGetJSONP(X) ((jsontype *) PG_DETOAST_DATUM(X))
#define JSONPGetDatum(X) PointerGetDatum(X)
#define PG_GETARG_JSON_P(n) DatumGetJSONP(PG_GETARG_DATUM(n))
#define PG_RETURN_JSON_P(x) PG_RETURN_POINTER(x)
void report_corrupt_json(void);
/* Keep the order of these enum entries in sync with
* enum_type_names[] in json_ops.c . */
typedef enum
{
JSON_NULL,
JSON_STRING,
JSON_NUMBER,
JSON_BOOL,
JSON_OBJECT,
JSON_ARRAY,
JSON_TYPE_COUNT = JSON_ARRAY + 1,
JSON_INVALID
} json_type;
#define json_type_is_valid(type) ((type) >= 0 && (type) < JSON_TYPE_COUNT)
typedef struct JSON JSON;
/*
* All strings in JSON nodes are UTF-8-encoded, not server encoded.
* The reason for this is because we need to encode/decode individual
* Unicode codepoints when dealing with escape characters, but there
* are no functions for efficiently converting between Unicode code points
* and any server encoding.
*
* As an exception to the rule, if you only use node factory functions and
* json_encode without the JSONOPT_ESCAPE_UNICODE option, you may operate
* in the server encoding instead.
*/
struct JSON
{
json_type type;
union
{
/* JSON_BOOL */
bool v_bool;
/* JSON_STRING */
struct
{
char *str;
size_t length;
} string;
/*
* JSON_NUMBER
*
* Numbers are encoded as strings to avoid unnecessary precision loss.
*/
char *number;
/* JSON_ARRAY or JSON_OBJECT (children) */
struct
{
JSON *head;
JSON *tail;
size_t count;
} children;
} v;
JSON *parent;
JSON *prev;
JSON *next;
/*
* If node is a member of an object, key will be set. Otherwise, key will
* be null.
*/
char *key;
size_t key_length;
struct json_orig
{
/* These only apply if this node is a member of an object. */
struct
{
const char *start;
const char *end;
} key_left_space, key, key_right_space;
struct
{
const char *start;
const char *end;
} left_space, value, right_space;
} orig;
/* Used by jp_set to indicate we should not visit this node again. */
bool jp_changed;
};
/*** Encoding / decoding / validation ***/
bool json_validate(const char *str);
bool json_validate_server_encoded(const char *str);
JSON *json_decode(const char *str);
#define JSONOPT_USE_ORIG 1
#define JSONOPT_ESCAPE_UNICODE 2
#define JSONOPT_NO_TRIM 4
char *json_encode(JSON * node, int options);
json_type json_text_type(const char *str, size_t nbytes);
/*** Lookup / traversal ***/
#define json_foreach(child, parent) \
for ((child) = json_head(parent); (child) != NULL; (child) = (child)->next)
static inline JSON *
json_head(JSON * parent)
{
switch (parent->type)
{
case JSON_ARRAY:
case JSON_OBJECT:
return parent->v.children.head;
default:
return NULL;
}
}
/*** Parent/child manipulation ***/
void json_append(JSON * parent, JSON * child);
void json_remove(JSON * node);
/*** Node factory functions ***/
JSON *json_mknode(json_type type);
JSON *json_mkbool(bool v_bool);
JSON *json_mkstring(const char *str, size_t length);
JSON *json_mknumber(const char *number, size_t length);
static inline JSON *
json_mkarray(void)
{
return json_mknode(JSON_ARRAY);
}
static inline JSON *
json_mkobject(void)
{
return json_mknode(JSON_OBJECT);
}
/*** Value get/set functions ***/
void json_touch_value(JSON * node);
static inline bool
json_get_bool(JSON * node)
{
Assert(node->type == JSON_BOOL);
return node->v.v_bool;
}
static inline void
json_set_bool(JSON * node, bool v_bool)
{
Assert(node->type == JSON_BOOL);
node->v.v_bool = v_bool;
json_touch_value(node);
}
const char *json_get_string(JSON * node, size_t *length_out);
void json_set_string(JSON * node, const char *str, size_t length);
const char *json_get_number(JSON * node);
void json_set_number(JSON * node, const char *number, size_t length);
void json_replace_value(JSON * node, JSON * replacement);
/*** Miscellaneous utility functions ***/
char *json_decode_string(const char **sp, size_t *length, bool strict);
char *json_encode_string(const char *str, size_t length, char quote, bool escape_unicode);
#endif
|