1 /* json-gobject.c - JSON GObject integration
2 *
3 * This file is part of JSON-GLib
4 * Copyright (C) 2007 OpenedHand Ltd.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * Author:
17 * Emmanuele Bassi <ebassi@openedhand.com>
18 */
19
20 /**
21 * SECTION:json-serializable
22 * @short_description: Interface for serialize and deserialize special GObjects
23 *
24 * #JsonSerializable is an interface for #GObject classes that
25 * allows controlling how the class is going to be serialized
26 * or deserialized by json_construct_gobject() and
27 * json_serialize_gobject() respectively.
28 */
29
30 #include "config.h"
31
32 #include <string.h>
33 #include <stdlib.h>
34
35 #include "json-types-private.h"
36 #include "json-gobject-private.h"
37 #include "json-debug.h"
38
39 /**
40 * json_serializable_serialize_property:
41 * @serializable: a #JsonSerializable object
42 * @property_name: the name of the property
43 * @value: the value of the property
44 * @pspec: a #GParamSpec
45 *
46 * Asks a #JsonSerializable implementation to serialize a #GObject
47 * property into a #JsonNode object.
48 *
49 * Return value: a #JsonNode containing the serialized property
50 */
51 JsonNode *
json_serializable_serialize_property(JsonSerializable * serializable,const gchar * property_name,const GValue * value,GParamSpec * pspec)52 json_serializable_serialize_property (JsonSerializable *serializable,
53 const gchar *property_name,
54 const GValue *value,
55 GParamSpec *pspec)
56 {
57 JsonSerializableIface *iface;
58
59 g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
60 g_return_val_if_fail (property_name != NULL, NULL);
61 g_return_val_if_fail (value != NULL, NULL);
62 g_return_val_if_fail (pspec != NULL, NULL);
63
64 iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
65
66 return iface->serialize_property (serializable, property_name, value, pspec);
67 }
68
69 /**
70 * json_serializable_deserialize_property:
71 * @serializable: a #JsonSerializable
72 * @property_name: the name of the property
73 * @value: (out): a pointer to an uninitialized #GValue
74 * @pspec: a #GParamSpec
75 * @property_node: a #JsonNode containing the serialized property
76 *
77 * Asks a #JsonSerializable implementation to deserialize the
78 * property contained inside @property_node into @value.
79 *
80 * The @value can be:
81 * - an empty #GValue initialized by %G_VALUE_INIT, which will be automatically
82 * initialized with the expected type of the property (since JSON-GLib 1.6)
83 * - a #GValue initialized with the expected type of the property
84 *
85 * Return value: %TRUE if the property was successfully deserialized.
86 */
87 gboolean
json_serializable_deserialize_property(JsonSerializable * serializable,const gchar * property_name,GValue * value,GParamSpec * pspec,JsonNode * property_node)88 json_serializable_deserialize_property (JsonSerializable *serializable,
89 const gchar *property_name,
90 GValue *value,
91 GParamSpec *pspec,
92 JsonNode *property_node)
93 {
94 JsonSerializableIface *iface;
95
96 g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), FALSE);
97 g_return_val_if_fail (property_name != NULL, FALSE);
98 g_return_val_if_fail (value != NULL, FALSE);
99 g_return_val_if_fail (pspec != NULL, FALSE);
100 g_return_val_if_fail (property_node != NULL, FALSE);
101
102 iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
103
104 return iface->deserialize_property (serializable,
105 property_name,
106 value,
107 pspec,
108 property_node);
109 }
110
111 static gboolean
json_serializable_real_deserialize(JsonSerializable * serializable,const gchar * name,GValue * value,GParamSpec * pspec,JsonNode * node)112 json_serializable_real_deserialize (JsonSerializable *serializable,
113 const gchar *name,
114 GValue *value,
115 GParamSpec *pspec,
116 JsonNode *node)
117 {
118 JSON_NOTE (GOBJECT, "Default deserialization for property '%s'", pspec->name);
119
120 if (!G_IS_VALUE (value))
121 g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
122
123 return json_deserialize_pspec (value, pspec, node);
124 }
125
126 static JsonNode *
json_serializable_real_serialize(JsonSerializable * serializable,const gchar * name,const GValue * value,GParamSpec * pspec)127 json_serializable_real_serialize (JsonSerializable *serializable,
128 const gchar *name,
129 const GValue *value,
130 GParamSpec *pspec)
131 {
132 JSON_NOTE (GOBJECT, "Default serialization for property '%s'", pspec->name);
133
134 if (g_param_value_defaults (pspec, (GValue *)value))
135 return NULL;
136
137 return json_serialize_pspec (value, pspec);
138 }
139
140 static GParamSpec *
json_serializable_real_find_property(JsonSerializable * serializable,const char * name)141 json_serializable_real_find_property (JsonSerializable *serializable,
142 const char *name)
143 {
144 return g_object_class_find_property (G_OBJECT_GET_CLASS (serializable), name);
145 }
146
147 static GParamSpec **
json_serializable_real_list_properties(JsonSerializable * serializable,guint * n_pspecs)148 json_serializable_real_list_properties (JsonSerializable *serializable,
149 guint *n_pspecs)
150 {
151 return g_object_class_list_properties (G_OBJECT_GET_CLASS (serializable), n_pspecs);
152 }
153
154 static void
json_serializable_real_set_property(JsonSerializable * serializable,GParamSpec * pspec,const GValue * value)155 json_serializable_real_set_property (JsonSerializable *serializable,
156 GParamSpec *pspec,
157 const GValue *value)
158 {
159 g_object_set_property (G_OBJECT (serializable), pspec->name, value);
160 }
161
162 static void
json_serializable_real_get_property(JsonSerializable * serializable,GParamSpec * pspec,GValue * value)163 json_serializable_real_get_property (JsonSerializable *serializable,
164 GParamSpec *pspec,
165 GValue *value)
166 {
167 g_object_get_property (G_OBJECT (serializable), pspec->name, value);
168 }
169
170 /* typedef to satisfy G_DEFINE_INTERFACE's naming */
171 typedef JsonSerializableIface JsonSerializableInterface;
172
173 static void
json_serializable_default_init(JsonSerializableInterface * iface)174 json_serializable_default_init (JsonSerializableInterface *iface)
175 {
176 iface->serialize_property = json_serializable_real_serialize;
177 iface->deserialize_property = json_serializable_real_deserialize;
178 iface->find_property = json_serializable_real_find_property;
179 iface->list_properties = json_serializable_real_list_properties;
180 iface->set_property = json_serializable_real_set_property;
181 iface->get_property = json_serializable_real_get_property;
182 }
183
184 G_DEFINE_INTERFACE (JsonSerializable, json_serializable, G_TYPE_OBJECT);
185
186 /**
187 * json_serializable_default_serialize_property:
188 * @serializable: a #JsonSerializable object
189 * @property_name: the name of the property
190 * @value: the value of the property
191 * @pspec: a #GParamSpec
192 *
193 * Calls the default implementation of the #JsonSerializable
194 * #JsonSerializableIface.serialize_property() virtual function.
195 *
196 * This function can be used inside a custom implementation
197 * of the #JsonSerializableIface.serialize_property() virtual
198 * function in lieu of calling the default implementation
199 * through g_type_default_interface_peek():
200 *
201 * |[<!-- language="C" -->
202 * JsonSerializable *iface;
203 * JsonNode *node;
204 *
205 * iface = g_type_default_interface_peek (JSON_TYPE_SERIALIZABLE);
206 * node = iface->serialize_property (serializable, property_name,
207 * value,
208 * pspec);
209 * ]|
210 *
211 * Return value: (transfer full) (nullable): a #JsonNode containing the
212 * serialized property, or %NULL if it should be omitted.
213 *
214 * Since: 0.10
215 */
216 JsonNode *
json_serializable_default_serialize_property(JsonSerializable * serializable,const gchar * property_name,const GValue * value,GParamSpec * pspec)217 json_serializable_default_serialize_property (JsonSerializable *serializable,
218 const gchar *property_name,
219 const GValue *value,
220 GParamSpec *pspec)
221 {
222 g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
223 g_return_val_if_fail (property_name != NULL, NULL);
224 g_return_val_if_fail (value != NULL, NULL);
225 g_return_val_if_fail (pspec != NULL, NULL);
226
227 return json_serializable_real_serialize (serializable,
228 property_name,
229 value, pspec);
230 }
231
232 /**
233 * json_serializable_default_deserialize_property:
234 * @serializable: a #JsonSerializable
235 * @property_name: the name of the property
236 * @value: a pointer to an uninitialized #GValue
237 * @pspec: a #GParamSpec
238 * @property_node: a #JsonNode containing the serialized property
239 *
240 * Calls the default implementation of the #JsonSerializable
241 * deserialize_property() virtual function
242 *
243 * This function can be used inside a custom implementation
244 * of the deserialize_property() virtual function in lieu of:
245 *
246 * |[<!-- language="C" -->
247 * JsonSerializable *iface;
248 * gboolean res;
249 *
250 * iface = g_type_default_interface_peek (JSON_TYPE_SERIALIZABLE);
251 * res = iface->deserialize_property (serializable, property_name,
252 * value,
253 * pspec,
254 * property_node);
255 * ]|
256 *
257 * Return value: %TRUE if the property was successfully deserialized.
258 *
259 * Since: 0.10
260 */
261 gboolean
json_serializable_default_deserialize_property(JsonSerializable * serializable,const gchar * property_name,GValue * value,GParamSpec * pspec,JsonNode * property_node)262 json_serializable_default_deserialize_property (JsonSerializable *serializable,
263 const gchar *property_name,
264 GValue *value,
265 GParamSpec *pspec,
266 JsonNode *property_node)
267 {
268 g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), FALSE);
269 g_return_val_if_fail (property_name != NULL, FALSE);
270 g_return_val_if_fail (value != NULL, FALSE);
271 g_return_val_if_fail (pspec != NULL, FALSE);
272 g_return_val_if_fail (property_node != NULL, FALSE);
273
274 return json_serializable_real_deserialize (serializable,
275 property_name,
276 value, pspec,
277 property_node);
278 }
279
280 /**
281 * json_serializable_find_property:
282 * @serializable: a #JsonSerializable
283 * @name: the name of the property
284 *
285 * Calls the #JsonSerializableIface.find_property() implementation on
286 * the @serializable instance. *
287 *
288 * Return value: (nullable) (transfer none): the #GParamSpec for the property
289 * or %NULL if no property was found
290 *
291 * Since: 0.14
292 */
293 GParamSpec *
json_serializable_find_property(JsonSerializable * serializable,const char * name)294 json_serializable_find_property (JsonSerializable *serializable,
295 const char *name)
296 {
297 g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
298 g_return_val_if_fail (name != NULL, NULL);
299
300 return JSON_SERIALIZABLE_GET_IFACE (serializable)->find_property (serializable, name);
301 }
302
303 /**
304 * json_serializable_list_properties:
305 * @serializable: a #JsonSerializable
306 * @n_pspecs: (out): return location for the length of the array
307 * of #GParamSpec returned by the function
308 *
309 * Calls the #JsonSerializableIface.list_properties() implementation on
310 * the @serializable instance.
311 *
312 * Return value: (array length=n_pspecs) (transfer container): an array
313 * of #GParamSpec. Use g_free() to free the array when done.
314 *
315 * Since: 0.14
316 */
317 GParamSpec **
json_serializable_list_properties(JsonSerializable * serializable,guint * n_pspecs)318 json_serializable_list_properties (JsonSerializable *serializable,
319 guint *n_pspecs)
320 {
321 g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
322
323 return JSON_SERIALIZABLE_GET_IFACE (serializable)->list_properties (serializable, n_pspecs);
324 }
325
326 /**
327 * json_serializable_set_property:
328 * @serializable: a #JsonSerializable
329 * @pspec: a #GParamSpec
330 * @value: the property value to set
331 *
332 * Calls the #JsonSerializableIface.set_property() implementation
333 * on the @serializable instance.
334 *
335 * Since: 0.14
336 */
337 void
json_serializable_set_property(JsonSerializable * serializable,GParamSpec * pspec,const GValue * value)338 json_serializable_set_property (JsonSerializable *serializable,
339 GParamSpec *pspec,
340 const GValue *value)
341 {
342 g_return_if_fail (JSON_IS_SERIALIZABLE (serializable));
343 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
344 g_return_if_fail (value != NULL);
345
346 JSON_SERIALIZABLE_GET_IFACE (serializable)->set_property (serializable,
347 pspec,
348 value);
349 }
350
351 /**
352 * json_serializable_get_property:
353 * @serializable: a #JsonSerializable
354 * @pspec: a #GParamSpec
355 * @value: (out): return location for the property value
356 *
357 * Calls the #JsonSerializableIface.get_property() implementation
358 * on the @serializable instance.
359 *
360 * Since: 0.14
361 */
362 void
json_serializable_get_property(JsonSerializable * serializable,GParamSpec * pspec,GValue * value)363 json_serializable_get_property (JsonSerializable *serializable,
364 GParamSpec *pspec,
365 GValue *value)
366 {
367 g_return_if_fail (JSON_IS_SERIALIZABLE (serializable));
368 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
369 g_return_if_fail (value != NULL);
370
371 JSON_SERIALIZABLE_GET_IFACE (serializable)->get_property (serializable,
372 pspec,
373 value);
374 }
375