├── 3rd ├── inc │ ├── jansson.h │ └── jansson_config.h └── lib │ └── libjansson.a ├── LICENSE ├── Makefile ├── README.md ├── README_EN.md ├── adapter ├── cjson │ ├── cJSON.c │ ├── cJSON.h │ └── cjson_impl.c └── jansson │ └── jansson_impl.c ├── demo ├── Makefile ├── main.c ├── test.c └── test2.c ├── inc └── cson.h └── src └── cson.c /3rd/inc/jansson.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009-2016 Petri Lehtinen 3 | * 4 | * Jansson is free software; you can redistribute it and/or modify 5 | * it under the terms of the MIT license. See LICENSE for details. 6 | */ 7 | 8 | #ifndef JANSSON_H 9 | #define JANSSON_H 10 | 11 | #include 12 | #include /* for size_t */ 13 | #include 14 | 15 | #include "jansson_config.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /* version */ 22 | 23 | #define JANSSON_MAJOR_VERSION 2 24 | #define JANSSON_MINOR_VERSION 12 25 | #define JANSSON_MICRO_VERSION 0 26 | 27 | /* Micro version is omitted if it's 0 */ 28 | #define JANSSON_VERSION "2.12" 29 | 30 | /* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this 31 | for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */ 32 | #define JANSSON_VERSION_HEX ((JANSSON_MAJOR_VERSION << 16) | \ 33 | (JANSSON_MINOR_VERSION << 8) | \ 34 | (JANSSON_MICRO_VERSION << 0)) 35 | 36 | /* If __atomic or __sync builtins are available the library is thread 37 | * safe for all read-only functions plus reference counting. */ 38 | #if JSON_HAVE_ATOMIC_BUILTINS || JSON_HAVE_SYNC_BUILTINS 39 | #define JANSSON_THREAD_SAFE_REFCOUNT 1 40 | #endif 41 | 42 | #if defined(__GNUC__) || defined(__clang__) 43 | #define JANSSON_ATTRS(...) __attribute__((__VA_ARGS__)) 44 | #else 45 | #define JANSSON_ATTRS(...) 46 | #endif 47 | 48 | /* types */ 49 | 50 | typedef enum { 51 | JSON_OBJECT, 52 | JSON_ARRAY, 53 | JSON_STRING, 54 | JSON_INTEGER, 55 | JSON_REAL, 56 | JSON_TRUE, 57 | JSON_FALSE, 58 | JSON_NULL 59 | } json_type; 60 | 61 | typedef struct json_t { 62 | json_type type; 63 | volatile size_t refcount; 64 | } json_t; 65 | 66 | #ifndef JANSSON_USING_CMAKE /* disabled if using cmake */ 67 | #if JSON_INTEGER_IS_LONG_LONG 68 | #ifdef _WIN32 69 | #define JSON_INTEGER_FORMAT "I64d" 70 | #else 71 | #define JSON_INTEGER_FORMAT "lld" 72 | #endif 73 | typedef long long json_int_t; 74 | #else 75 | #define JSON_INTEGER_FORMAT "ld" 76 | typedef long json_int_t; 77 | #endif /* JSON_INTEGER_IS_LONG_LONG */ 78 | #endif 79 | 80 | #define json_typeof(json) ((json)->type) 81 | #define json_is_object(json) ((json) && json_typeof(json) == JSON_OBJECT) 82 | #define json_is_array(json) ((json) && json_typeof(json) == JSON_ARRAY) 83 | #define json_is_string(json) ((json) && json_typeof(json) == JSON_STRING) 84 | #define json_is_integer(json) ((json) && json_typeof(json) == JSON_INTEGER) 85 | #define json_is_real(json) ((json) && json_typeof(json) == JSON_REAL) 86 | #define json_is_number(json) (json_is_integer(json) || json_is_real(json)) 87 | #define json_is_true(json) ((json) && json_typeof(json) == JSON_TRUE) 88 | #define json_is_false(json) ((json) && json_typeof(json) == JSON_FALSE) 89 | #define json_boolean_value json_is_true 90 | #define json_is_boolean(json) (json_is_true(json) || json_is_false(json)) 91 | #define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL) 92 | 93 | /* construction, destruction, reference counting */ 94 | 95 | json_t *json_object(void); 96 | json_t *json_array(void); 97 | json_t *json_string(const char *value); 98 | json_t *json_stringn(const char *value, size_t len); 99 | json_t *json_string_nocheck(const char *value); 100 | json_t *json_stringn_nocheck(const char *value, size_t len); 101 | json_t *json_integer(json_int_t value); 102 | json_t *json_real(double value); 103 | json_t *json_true(void); 104 | json_t *json_false(void); 105 | #define json_boolean(val) ((val) ? json_true() : json_false()) 106 | json_t *json_null(void); 107 | 108 | /* do not call JSON_INTERNAL_INCREF or JSON_INTERNAL_DECREF directly */ 109 | #if JSON_HAVE_ATOMIC_BUILTINS 110 | #define JSON_INTERNAL_INCREF(json) __atomic_add_fetch(&json->refcount, 1, __ATOMIC_ACQUIRE) 111 | #define JSON_INTERNAL_DECREF(json) __atomic_sub_fetch(&json->refcount, 1, __ATOMIC_RELEASE) 112 | #elif JSON_HAVE_SYNC_BUILTINS 113 | #define JSON_INTERNAL_INCREF(json) __sync_add_and_fetch(&json->refcount, 1) 114 | #define JSON_INTERNAL_DECREF(json) __sync_sub_and_fetch(&json->refcount, 1) 115 | #else 116 | #define JSON_INTERNAL_INCREF(json) (++json->refcount) 117 | #define JSON_INTERNAL_DECREF(json) (--json->refcount) 118 | #endif 119 | 120 | static JSON_INLINE 121 | json_t *json_incref(json_t *json) 122 | { 123 | if(json && json->refcount != (size_t)-1) 124 | JSON_INTERNAL_INCREF(json); 125 | return json; 126 | } 127 | 128 | /* do not call json_delete directly */ 129 | void json_delete(json_t *json); 130 | 131 | static JSON_INLINE 132 | void json_decref(json_t *json) 133 | { 134 | if(json && json->refcount != (size_t)-1 && JSON_INTERNAL_DECREF(json) == 0) 135 | json_delete(json); 136 | } 137 | 138 | #if defined(__GNUC__) || defined(__clang__) 139 | static JSON_INLINE 140 | void json_decrefp(json_t **json) 141 | { 142 | if(json) { 143 | json_decref(*json); 144 | *json = NULL; 145 | } 146 | } 147 | 148 | #define json_auto_t json_t __attribute__((cleanup(json_decrefp))) 149 | #endif 150 | 151 | 152 | /* error reporting */ 153 | 154 | #define JSON_ERROR_TEXT_LENGTH 160 155 | #define JSON_ERROR_SOURCE_LENGTH 80 156 | 157 | typedef struct json_error_t { 158 | int line; 159 | int column; 160 | int position; 161 | char source[JSON_ERROR_SOURCE_LENGTH]; 162 | char text[JSON_ERROR_TEXT_LENGTH]; 163 | } json_error_t; 164 | 165 | enum json_error_code { 166 | json_error_unknown, 167 | json_error_out_of_memory, 168 | json_error_stack_overflow, 169 | json_error_cannot_open_file, 170 | json_error_invalid_argument, 171 | json_error_invalid_utf8, 172 | json_error_premature_end_of_input, 173 | json_error_end_of_input_expected, 174 | json_error_invalid_syntax, 175 | json_error_invalid_format, 176 | json_error_wrong_type, 177 | json_error_null_character, 178 | json_error_null_value, 179 | json_error_null_byte_in_key, 180 | json_error_duplicate_key, 181 | json_error_numeric_overflow, 182 | json_error_item_not_found, 183 | json_error_index_out_of_range 184 | }; 185 | 186 | static JSON_INLINE enum json_error_code json_error_code(const json_error_t *e) { 187 | return (enum json_error_code)e->text[JSON_ERROR_TEXT_LENGTH - 1]; 188 | } 189 | 190 | /* getters, setters, manipulation */ 191 | 192 | void json_object_seed(size_t seed); 193 | size_t json_object_size(const json_t *object); 194 | json_t *json_object_get(const json_t *object, const char *key) JANSSON_ATTRS(warn_unused_result); 195 | int json_object_set_new(json_t *object, const char *key, json_t *value); 196 | int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value); 197 | int json_object_del(json_t *object, const char *key); 198 | int json_object_clear(json_t *object); 199 | int json_object_update(json_t *object, json_t *other); 200 | int json_object_update_existing(json_t *object, json_t *other); 201 | int json_object_update_missing(json_t *object, json_t *other); 202 | void *json_object_iter(json_t *object); 203 | void *json_object_iter_at(json_t *object, const char *key); 204 | void *json_object_key_to_iter(const char *key); 205 | void *json_object_iter_next(json_t *object, void *iter); 206 | const char *json_object_iter_key(void *iter); 207 | json_t *json_object_iter_value(void *iter); 208 | int json_object_iter_set_new(json_t *object, void *iter, json_t *value); 209 | 210 | #define json_object_foreach(object, key, value) \ 211 | for(key = json_object_iter_key(json_object_iter(object)); \ 212 | key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ 213 | key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key)))) 214 | 215 | #define json_object_foreach_safe(object, n, key, value) \ 216 | for(key = json_object_iter_key(json_object_iter(object)), \ 217 | n = json_object_iter_next(object, json_object_key_to_iter(key)); \ 218 | key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ 219 | key = json_object_iter_key(n), \ 220 | n = json_object_iter_next(object, json_object_key_to_iter(key))) 221 | 222 | #define json_array_foreach(array, index, value) \ 223 | for(index = 0; \ 224 | index < json_array_size(array) && (value = json_array_get(array, index)); \ 225 | index++) 226 | 227 | static JSON_INLINE 228 | int json_object_set(json_t *object, const char *key, json_t *value) 229 | { 230 | return json_object_set_new(object, key, json_incref(value)); 231 | } 232 | 233 | static JSON_INLINE 234 | int json_object_set_nocheck(json_t *object, const char *key, json_t *value) 235 | { 236 | return json_object_set_new_nocheck(object, key, json_incref(value)); 237 | } 238 | 239 | static JSON_INLINE 240 | int json_object_iter_set(json_t *object, void *iter, json_t *value) 241 | { 242 | return json_object_iter_set_new(object, iter, json_incref(value)); 243 | } 244 | 245 | size_t json_array_size(const json_t *array); 246 | json_t *json_array_get(const json_t *array, size_t index) JANSSON_ATTRS(warn_unused_result); 247 | int json_array_set_new(json_t *array, size_t index, json_t *value); 248 | int json_array_append_new(json_t *array, json_t *value); 249 | int json_array_insert_new(json_t *array, size_t index, json_t *value); 250 | int json_array_remove(json_t *array, size_t index); 251 | int json_array_clear(json_t *array); 252 | int json_array_extend(json_t *array, json_t *other); 253 | 254 | static JSON_INLINE 255 | int json_array_set(json_t *array, size_t ind, json_t *value) 256 | { 257 | return json_array_set_new(array, ind, json_incref(value)); 258 | } 259 | 260 | static JSON_INLINE 261 | int json_array_append(json_t *array, json_t *value) 262 | { 263 | return json_array_append_new(array, json_incref(value)); 264 | } 265 | 266 | static JSON_INLINE 267 | int json_array_insert(json_t *array, size_t ind, json_t *value) 268 | { 269 | return json_array_insert_new(array, ind, json_incref(value)); 270 | } 271 | 272 | const char *json_string_value(const json_t *string); 273 | size_t json_string_length(const json_t *string); 274 | json_int_t json_integer_value(const json_t *integer); 275 | double json_real_value(const json_t *real); 276 | double json_number_value(const json_t *json); 277 | 278 | int json_string_set(json_t *string, const char *value); 279 | int json_string_setn(json_t *string, const char *value, size_t len); 280 | int json_string_set_nocheck(json_t *string, const char *value); 281 | int json_string_setn_nocheck(json_t *string, const char *value, size_t len); 282 | int json_integer_set(json_t *integer, json_int_t value); 283 | int json_real_set(json_t *real, double value); 284 | 285 | /* pack, unpack */ 286 | 287 | json_t *json_pack(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result); 288 | json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) JANSSON_ATTRS(warn_unused_result); 289 | json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result); 290 | 291 | #define JSON_VALIDATE_ONLY 0x1 292 | #define JSON_STRICT 0x2 293 | 294 | int json_unpack(json_t *root, const char *fmt, ...); 295 | int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...); 296 | int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, va_list ap); 297 | 298 | /* sprintf */ 299 | 300 | json_t *json_sprintf(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 2)); 301 | json_t *json_vsprintf(const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 0)); 302 | 303 | 304 | /* equality */ 305 | 306 | int json_equal(const json_t *value1, const json_t *value2); 307 | 308 | 309 | /* copying */ 310 | 311 | json_t *json_copy(json_t *value) JANSSON_ATTRS(warn_unused_result); 312 | json_t *json_deep_copy(const json_t *value) JANSSON_ATTRS(warn_unused_result); 313 | 314 | 315 | /* decoding */ 316 | 317 | #define JSON_REJECT_DUPLICATES 0x1 318 | #define JSON_DISABLE_EOF_CHECK 0x2 319 | #define JSON_DECODE_ANY 0x4 320 | #define JSON_DECODE_INT_AS_REAL 0x8 321 | #define JSON_ALLOW_NUL 0x10 322 | 323 | typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); 324 | 325 | json_t *json_loads(const char *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); 326 | json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); 327 | json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); 328 | json_t *json_loadfd(int input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); 329 | json_t *json_load_file(const char *path, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); 330 | json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); 331 | 332 | 333 | /* encoding */ 334 | 335 | #define JSON_MAX_INDENT 0x1F 336 | #define JSON_INDENT(n) ((n) & JSON_MAX_INDENT) 337 | #define JSON_COMPACT 0x20 338 | #define JSON_ENSURE_ASCII 0x40 339 | #define JSON_SORT_KEYS 0x80 340 | #define JSON_PRESERVE_ORDER 0x100 341 | #define JSON_ENCODE_ANY 0x200 342 | #define JSON_ESCAPE_SLASH 0x400 343 | #define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11) 344 | #define JSON_EMBED 0x10000 345 | 346 | typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); 347 | 348 | char *json_dumps(const json_t *json, size_t flags) JANSSON_ATTRS(warn_unused_result); 349 | size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags); 350 | int json_dumpf(const json_t *json, FILE *output, size_t flags); 351 | int json_dumpfd(const json_t *json, int output, size_t flags); 352 | int json_dump_file(const json_t *json, const char *path, size_t flags); 353 | int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags); 354 | 355 | /* custom memory allocation */ 356 | 357 | typedef void *(*json_malloc_t)(size_t); 358 | typedef void (*json_free_t)(void *); 359 | 360 | void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn); 361 | void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn); 362 | 363 | #ifdef __cplusplus 364 | } 365 | #endif 366 | 367 | #endif 368 | -------------------------------------------------------------------------------- /3rd/inc/jansson_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2016 Petri Lehtinen 3 | * 4 | * Jansson is free software; you can redistribute it and/or modify 5 | * it under the terms of the MIT license. See LICENSE for details. 6 | * 7 | * 8 | * This file specifies a part of the site-specific configuration for 9 | * Jansson, namely those things that affect the public API in 10 | * jansson.h. 11 | * 12 | * The configure script copies this file to jansson_config.h and 13 | * replaces @var@ substitutions by values that fit your system. If you 14 | * cannot run the configure script, you can do the value substitution 15 | * by hand. 16 | */ 17 | 18 | #ifndef JANSSON_CONFIG_H 19 | #define JANSSON_CONFIG_H 20 | 21 | /* If your compiler supports the inline keyword in C, JSON_INLINE is 22 | defined to `inline', otherwise empty. In C++, the inline is always 23 | supported. */ 24 | #ifdef __cplusplus 25 | #define JSON_INLINE inline 26 | #else 27 | #define JSON_INLINE inline 28 | #endif 29 | 30 | /* If your compiler supports the `long long` type and the strtoll() 31 | library function, JSON_INTEGER_IS_LONG_LONG is defined to 1, 32 | otherwise to 0. */ 33 | #define JSON_INTEGER_IS_LONG_LONG 1 34 | 35 | /* If locale.h and localeconv() are available, define to 1, 36 | otherwise to 0. */ 37 | #define JSON_HAVE_LOCALECONV 1 38 | 39 | /* If __atomic builtins are available they will be used to manage 40 | reference counts of json_t. */ 41 | #define JSON_HAVE_ATOMIC_BUILTINS 1 42 | 43 | /* If __atomic builtins are not available we try using __sync builtins 44 | to manage reference counts of json_t. */ 45 | #define JSON_HAVE_SYNC_BUILTINS 1 46 | 47 | /* Maximum recursion depth for parsing JSON input. 48 | This limits the depth of e.g. array-within-array constructions. */ 49 | #define JSON_PARSER_MAX_DEPTH 2048 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /3rd/lib/libjansson.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunchb/cson/fb21e176638353ebbb49f155fb7f02790c6ecafd/3rd/lib/libjansson.a -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 sunchb (sun_chb@126.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Define the command of tool 2 | CC := gcc 3 | AR := ar 4 | MD := mkdir -p 5 | RM := rm -rf 6 | 7 | # Define the JSON parsing library used (cjson or jansson supported) 8 | JSON_LIB = cjson 9 | #JSON_LIB = jansson 10 | 11 | # output files 12 | OUT_DIR := ./output 13 | TARGET := $(OUT_DIR)/libcson.a 14 | 15 | # source files 16 | SRC_DIR = ./src 17 | SRC_FILES += $(wildcard $(SRC_DIR)/*.c) 18 | 19 | ADP_SRC_DIR = ./adapter/$(JSON_LIB) 20 | ADP_SRC_FILES += $(wildcard $(ADP_SRC_DIR)/*.c) 21 | 22 | # *.o 23 | OBJS += $(patsubst $(SRC_DIR)/%.c, $(OUT_DIR)/%.o, $(SRC_FILES)) 24 | OBJS += $(patsubst $(ADP_SRC_DIR)/%.c, $(OUT_DIR)/%.o, $(ADP_SRC_FILES)) 25 | 26 | # include path 27 | INC_PATH += -I./inc/ 28 | INC_PATH += -I./3rd/inc/ 29 | 30 | $(TARGET):$(OBJS) 31 | @$(MD) $(OUT_DIR) 32 | @$(AR) rc $(TARGET) $(OBJS) 33 | 34 | $(OUT_DIR)/%.o:$(SRC_DIR)/%.c 35 | @$(MD) $(OUT_DIR) 36 | @$(CC) $(INC_PATH) -c $< -o $@ 37 | 38 | $(OUT_DIR)/%.o:$(ADP_SRC_DIR)/%.c 39 | @$(MD) $(OUT_DIR) 40 | @$(CC) $(INC_PATH) -c $< -o $@ 41 | 42 | .PHONY:clean 43 | clean: 44 | @$(RM) $(OUT_DIR) 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 简体中文 | [English](./README_EN.md) 2 | 3 | # cson 4 | 轻松完成C语言结构体和Json的转换。 5 | 6 | 其中Json字符串与Json对象(例如Jansson库中的json_t)之间的转换由第三方库实现(例如Jansson或者cJSON,请参考依赖库)。 7 | cson真正实现的是Json对象与结构体间的转换。 8 | 9 | ## 编译 10 | ### 编译静态库 11 | ``` shell 12 | $ git clone https://github.com/sunchb/cson.git 13 | $ cd cson 14 | $ make 15 | ``` 16 | ### 编译示例 17 | ``` shell 18 | $ cd demo 19 | $ make 20 | $ ./test 21 | ``` 22 | ## 如何使用cson 23 | 1. 定义与Json协议对应的结构体。 24 | 2. 定义结构体的属性描述表。 25 | 3. 调用cson接口完成转换。 26 | 27 | ## 依赖 28 | https://github.com/akheron/jansson.git 29 | https://github.com/DaveGamble/cJSON.git 30 | 31 | ## 示例 32 | 下面具有各种数据类型的JSON。例如整数,字符串,实数,布尔值,对象和数组。我们将通过cson对其进行解码和编码。 33 | 34 | ``` json 35 | { 36 | "name":"jay zhou", 37 | "creater":"dahuaxia", 38 | "songNum":2, 39 | "songList":[ 40 | { 41 | "songName":"qilixiang", 42 | "signerName":"jay zhou", 43 | "albumName":"qilixiang", 44 | "url":"www.kugou.com", 45 | "duration":200, 46 | "paid":false, 47 | "price":6.6600000000000001, 48 | "lyricNum":2, 49 | "lyric":[ 50 | { 51 | "time":1, 52 | "text":"Sparrow outside the window" 53 | }, 54 | { 55 | "time":10, 56 | "text":"Multi mouth on the pole" 57 | } 58 | ] 59 | }, 60 | { 61 | "songName":"dongfengpo", 62 | "signerName":"jay zhou", 63 | "albumName":"dongfengpo", 64 | "url":"music.qq.com", 65 | "duration":180, 66 | "paid":true, 67 | "price":0.88, 68 | "lyricNum":2, 69 | "lyric":[ 70 | { 71 | "time":10, 72 | "text":"A sad parting, standing alone in the window" 73 | }, 74 | { 75 | "time":20, 76 | "text":"I'm behind the door pretending you're not gone" 77 | } 78 | ] 79 | } 80 | ], 81 | "extData":{ 82 | "a":999, 83 | "b":1.05 84 | } 85 | } 86 | ``` 87 | 88 | ### 1. 定义与Json协议对应的结构体。 89 | 即使不使用cson,通常我们也会这么做。 90 | 91 | #### 注意事项 92 | - 字符串必须定义为char*类型。 93 | - 数组必须定义为指针类型。 94 | - 如果结构体包含数组,需要为每一个数组定义一个额外的属性,用于保存数组大小。 95 | - 结构体属性名必须与Json字段名一致。 96 | 97 | ``` c 98 | typedef struct { 99 | int time; 100 | char* text; /* String must be declared as char* */ 101 | } Lyric; 102 | 103 | typedef struct { 104 | char* songName; 105 | char* signerName; 106 | char* albumName; 107 | char* url; 108 | int duration; 109 | int paid; 110 | double price; 111 | size_t lyricNum; /* Declare additional properties to hold the array size */ 112 | Lyric* lyric; /* Array must be declared as pointer */ 113 | } SongInfo; 114 | 115 | typedef struct { 116 | int a; 117 | double b; 118 | } ExtData; 119 | 120 | typedef struct { 121 | char* name; 122 | char* creater; 123 | size_t songNum; 124 | SongInfo* songList; 125 | ExtData extData; 126 | } PlayList; 127 | ``` 128 | 129 | ### 2. 定义结构体的属性描述表。 130 | 使用以下宏定义描述结构体属性。 131 | - _property_int(type, field) 132 | - _property_real(type, field) 133 | - _property_bool(type, field) 134 | - _property_string(type, field) 135 | - _property_obj(type, field, tbl) 136 | - _property_array_object(type, field, tbl, arrayType, countfild) # I know it's a little cumbersome, I'm trying to simplify it. 137 | - _property_array_int(type, field, arrayType, countfild) 138 | - _property_array_string(type, field, arrayType, countfild) 139 | - _property_array_real(type, field, arrayType, countfild) 140 | - _property_array_bool(type, field, arrayType, countfild) 141 | 142 | 143 | 参数说明: 144 | - type: type of data structure 145 | - field: property name 146 | - tbl: description table of the property type. use when object or object array 147 | - arrayType: type of the array (Used to calculate size when dynamically get array memory) 148 | - countfild: property to save array size 149 | 150 | 也可以使用带有扩展参数的宏定义,其中args可以是_ex_args_nullable, _ex_args_exclude_decode, _ex_args_exclude_encode的组合。 151 | - #define _ex_args_nullable (0x01) //不会因为该字段异常而停止后续字段解析, 该选项默认打开。 152 | - #define _ex_args_exclude_decode (0x02) //该字段不参与解析————例如指示数组元素个数的字段,Json中可以不包含它 153 | - #define _ex_args_exclude_encode (0x04) //该字段不参与格式化输出 154 | - #define _ex_args_all (_ex_args_nullable | _ex_args_exclude_decode | _ex_args_exclude_encode) 155 | 156 | - _property_int_ex(type, field, args) 157 | - _property_real_ex(type, field, args) 158 | - _property_bool_ex(type, field, args) 159 | - _property_string_ex(type, field, args) 160 | - _property_obj_ex(type, field, tbl, args) 161 | - _property_array_ex(type, field, tbl, subType, count, args) 162 | - _property_array_object_ex(type, field, tbl, subType, count, args) 163 | - _property_array_int_ex(type, field, subType, count, args) 164 | - _property_array_string_ex(type, field, subType, count, args) 165 | - _property_array_real_ex(type, field, subType, count, args) 166 | - _property_array_bool_ex(type, field, subType, count, args) 167 | 168 | ``` c 169 | /* description for Lyric */ 170 | reflect_item_t lyric_ref_tbl[] = { 171 | _property_int(Lyric, time), 172 | _property_string(Lyric, text), 173 | _property_end() 174 | }; 175 | 176 | /* description for SongInfo */ 177 | reflect_item_t song_ref_tbl[] = { 178 | _property_string(SongInfo, songName), 179 | _property_string(SongInfo, signerName), 180 | _property_string(SongInfo, albumName), 181 | _property_string(SongInfo, url), 182 | _property_int(SongInfo, duration), 183 | _property_bool(SongInfo, paid), 184 | _property_real(SongInfo, price), 185 | _property_int_ex(SongInfo, lyricNum, _ex_args_all), 186 | _property_array(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum), /* Lyric: type of array; lyricNum: property to save array size */ 187 | _property_end() 188 | }; 189 | 190 | /* description for ExtData */ 191 | reflect_item_t ext_data_ref_tbl[] = { 192 | _property_int(ExtData, a), 193 | _property_real(ExtData, b), 194 | _property_end() 195 | }; 196 | 197 | /* description for PlayList */ 198 | reflect_item_t play_list_ref_tbl[] = { 199 | _property_string(PlayList, name), 200 | _property_string(PlayList, creater), 201 | _property_int_ex(PlayList, songNum, _ex_args_all), 202 | _property_array(PlayList, songList, song_ref_tbl, SongInfo, songNum), 203 | _property_obj(PlayList, extData, ext_data_ref_tbl), 204 | _property_end() 205 | }; 206 | ``` 207 | 208 | ### 3. 调用cson接口编解码Json。 209 | ``` c 210 | PlayList playList; 211 | 212 | /* Decode */ 213 | csonJsonStr2Struct(jStr, &playList, play_list_ref_tbl); 214 | 215 | /* Encode */ 216 | char* jstrOutput; 217 | csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl); 218 | ``` 219 | 220 | ## 限制 221 | - 暂不支持多维数组。 222 | - 默认使用Cjson库。如果需要使用jannson,请修改Makefile中的$(JSON_LIB)变量。 223 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | # [简体中文](./README.md) | English 2 | 3 | # cson 4 | Transformation between json string and struct. 5 | 6 | The transformation between string to JSON objects (e.g. json_t in Jansson) 7 | is implemented by a third-party library (Jansson or cJSON. Refer to Dependence). 8 | What cson really implements is the transformation between JSON object and structure. 9 | 10 | ## Compilation 11 | ### Compile static library 12 | ``` shell 13 | $ git clone https://github.com/sunchb/cson.git 14 | $ cd cson 15 | $ make 16 | ``` 17 | ### Compile demo 18 | ``` shell 19 | $ cd demo 20 | $ make 21 | $ ./test 22 | ``` 23 | ## How to use 24 | 1. Define the data structure for JSON. 25 | 2. Define the property description table for data structure. 26 | 3. Call cson api to decode or encode. 27 | 28 | ## Dependence 29 | https://github.com/akheron/jansson.git 30 | https://github.com/DaveGamble/cJSON.git 31 | 32 | ## Demo 33 | Here is a JSON with various data types. eg. Interger, String, Real, Boolean, Object, and Array. 34 | We're going to decode and encode it by cson. 35 | 36 | ``` json 37 | { 38 | "name":"jay zhou", 39 | "creater":"dahuaxia", 40 | "songNum":2, 41 | "songList":[ 42 | { 43 | "songName":"qilixiang", 44 | "signerName":"jay zhou", 45 | "albumName":"qilixiang", 46 | "url":"www.kugou.com", 47 | "duration":200, 48 | "paid":false, 49 | "price":6.6600000000000001, 50 | "lyricNum":2, 51 | "lyric":[ 52 | { 53 | "time":1, 54 | "text":"Sparrow outside the window" 55 | }, 56 | { 57 | "time":10, 58 | "text":"Multi mouth on the pole" 59 | } 60 | ] 61 | }, 62 | { 63 | "songName":"dongfengpo", 64 | "signerName":"jay zhou", 65 | "albumName":"dongfengpo", 66 | "url":"music.qq.com", 67 | "duration":180, 68 | "paid":true, 69 | "price":0.88, 70 | "lyricNum":2, 71 | "lyric":[ 72 | { 73 | "time":10, 74 | "text":"A sad parting, standing alone in the window" 75 | }, 76 | { 77 | "time":20, 78 | "text":"I'm behind the door pretending you're not gone" 79 | } 80 | ] 81 | } 82 | ], 83 | "extData":{ 84 | "a":999, 85 | "b":1.05 86 | } 87 | } 88 | ``` 89 | 90 | ### 1. Define the data structure for JSON. 91 | Even if you don't use cson, you usually need to do like this. 92 | 93 | #### Attention 94 | - String must be declared as char*. 95 | - Array must be declared as pointer. 96 | - Declare additional properties to hold the array size for every array property. 97 | - The structure property name must be the same as the JSON field name. 98 | 99 | ``` c 100 | typedef struct { 101 | int time; 102 | char* text; /* String must be declared as char* */ 103 | } Lyric; 104 | 105 | typedef struct { 106 | char* songName; 107 | char* signerName; 108 | char* albumName; 109 | char* url; 110 | int duration; 111 | int paid; 112 | double price; 113 | size_t lyricNum; /* Declare additional properties to hold the array size */ 114 | Lyric* lyric; /* Array must be declared as pointer */ 115 | } SongInfo; 116 | 117 | typedef struct { 118 | int a; 119 | double b; 120 | } ExtData; 121 | 122 | typedef struct { 123 | char* name; 124 | char* creater; 125 | size_t songNum; 126 | SongInfo* songList; 127 | ExtData extData; 128 | } PlayList; 129 | ``` 130 | 131 | ### 2. Define the property description table for data structure. 132 | Use following definitions to help you describe the structure. 133 | - _property_int(type, field) 134 | - _property_real(type, field) 135 | - _property_bool(type, field) 136 | - _property_string(type, field) 137 | - _property_obj(type, field, tbl) 138 | - _property_array_object(type, field, tbl, arrayType, countfild) # I know it's a little cumbersome, I'm trying to simplify it. 139 | - _property_array_int(type, field, arrayType, countfild) 140 | - _property_array_string(type, field, arrayType, countfild) 141 | - _property_array_real(type, field, arrayType, countfild) 142 | - _property_array_bool(type, field, arrayType, countfild) 143 | 144 | Args notes: 145 | - type: type of data structure 146 | - field: property name 147 | - tbl: description table of the property type. use when object or object array 148 | - arrayType: type of the array (Used to calculate size when dynamically get array memory) 149 | - countfild: property to save array size 150 | 151 | You can also use macro definitions with extended parameters, the range of args is _ex_args_nullable, _ex_args_exclude_decode, _ex_args_exclude_encode and thire combinations. 152 | - #define _ex_args_nullable (0x01) //continue parse or encode when the field exception occurred. Default is "ON". 153 | - #define _ex_args_exclude_decode (0x02) //do not parse the field. 154 | - #define _ex_args_exclude_encode (0x04) //do not encode the field. 155 | - #define _ex_args_all (_ex_args_nullable | _ex_args_exclude_decode | _ex_args_exclude_encode) 156 | 157 | - _property_int_ex(type, field, args) 158 | - _property_real_ex(type, field, args) 159 | - _property_bool_ex(type, field, args) 160 | - _property_string_ex(type, field, args) 161 | - _property_obj_ex(type, field, tbl, args) 162 | - _property_array_ex(type, field, tbl, subType, count, args) 163 | - _property_array_object_ex(type, field, tbl, subType, count, args) 164 | - _property_array_int_ex(type, field, subType, count, args) 165 | - _property_array_string_ex(type, field, subType, count, args) 166 | - _property_array_real_ex(type, field, subType, count, args) 167 | - _property_array_bool_ex(type, field, subType, count, args) 168 | 169 | ``` c 170 | /* description for Lyric */ 171 | reflect_item_t lyric_ref_tbl[] = { 172 | _property_int(Lyric, time), 173 | _property_string(Lyric, text), 174 | _property_end() 175 | }; 176 | 177 | /* description for SongInfo */ 178 | reflect_item_t song_ref_tbl[] = { 179 | _property_string(SongInfo, songName), 180 | _property_string(SongInfo, signerName), 181 | _property_string(SongInfo, albumName), 182 | _property_string(SongInfo, url), 183 | _property_int(SongInfo, duration), 184 | _property_bool(SongInfo, paid), 185 | _property_real(SongInfo, price), 186 | _property_int(SongInfo, lyricNum), 187 | _property_array(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum), /* Lyric: type of array; lyricNum: property to save array size */ 188 | _property_end() 189 | }; 190 | 191 | /* description for ExtData */ 192 | reflect_item_t ext_data_ref_tbl[] = { 193 | _property_int(ExtData, a), 194 | _property_real(ExtData, b), 195 | _property_end() 196 | }; 197 | 198 | /* description for PlayList */ 199 | reflect_item_t play_list_ref_tbl[] = { 200 | _property_string(PlayList, name), 201 | _property_string(PlayList, creater), 202 | _property_int(PlayList, songNum), 203 | _property_array(PlayList, songList, song_ref_tbl, SongInfo, songNum), 204 | _property_obj(PlayList, extData, ext_data_ref_tbl), 205 | _property_end() 206 | }; 207 | ``` 208 | 209 | ### 3. Call cson api to decode or encode. 210 | ``` c 211 | PlayList playList; 212 | 213 | /* Decode */ 214 | csonJsonStr2Struct(jStr, &playList, play_list_ref_tbl); 215 | 216 | /* Encode */ 217 | char* jstrOutput; 218 | csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl); 219 | ``` 220 | 221 | ## Restrict 222 | - Multidimensional arrays are not supported. 223 | - Cjson is used by default. If you want to use jannson or other json lib, please modify $(JSON_LIB) in makefile. 224 | -------------------------------------------------------------------------------- /adapter/cjson/cJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef cJSON__h 24 | #define cJSON__h 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) 32 | #define __WINDOWS__ 33 | #endif 34 | 35 | #ifdef __WINDOWS__ 36 | 37 | /* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: 38 | 39 | CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols 40 | CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) 41 | CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol 42 | 43 | For *nix builds that support visibility attribute, you can define similar behavior by 44 | 45 | setting default visibility to hidden by adding 46 | -fvisibility=hidden (for gcc) 47 | or 48 | -xldscope=hidden (for sun cc) 49 | to CFLAGS 50 | 51 | then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does 52 | 53 | */ 54 | 55 | #define CJSON_CDECL __cdecl 56 | #define CJSON_STDCALL __stdcall 57 | 58 | /* export symbols by default, this is necessary for copy pasting the C and header file */ 59 | #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) 60 | #define CJSON_EXPORT_SYMBOLS 61 | #endif 62 | 63 | #if defined(CJSON_HIDE_SYMBOLS) 64 | #define CJSON_PUBLIC(type) type CJSON_STDCALL 65 | #elif defined(CJSON_EXPORT_SYMBOLS) 66 | #define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL 67 | #elif defined(CJSON_IMPORT_SYMBOLS) 68 | #define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL 69 | #endif 70 | #else /* !__WINDOWS__ */ 71 | #define CJSON_CDECL 72 | #define CJSON_STDCALL 73 | 74 | #if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) 75 | #define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type 76 | #else 77 | #define CJSON_PUBLIC(type) type 78 | #endif 79 | #endif 80 | 81 | /* project version */ 82 | #define CJSON_VERSION_MAJOR 1 83 | #define CJSON_VERSION_MINOR 7 84 | #define CJSON_VERSION_PATCH 12 85 | 86 | #include 87 | 88 | /* cJSON Types: */ 89 | #define cJSON_Invalid (0) 90 | #define cJSON_False (1 << 0) 91 | #define cJSON_True (1 << 1) 92 | #define cJSON_NULL (1 << 2) 93 | #define cJSON_Number (1 << 3) 94 | #define cJSON_String (1 << 4) 95 | #define cJSON_Array (1 << 5) 96 | #define cJSON_Object (1 << 6) 97 | #define cJSON_Raw (1 << 7) /* raw json */ 98 | 99 | #define cJSON_IsReference 256 100 | #define cJSON_StringIsConst 512 101 | 102 | /* The cJSON structure: */ 103 | typedef struct cJSON 104 | { 105 | /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 106 | struct cJSON *next; 107 | struct cJSON *prev; 108 | /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 109 | struct cJSON *child; 110 | 111 | /* The type of the item, as above. */ 112 | int type; 113 | 114 | /* The item's string, if type==cJSON_String and type == cJSON_Raw */ 115 | char *valuestring; 116 | /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ 117 | int valueint; 118 | /* The item's number, if type==cJSON_Number */ 119 | double valuedouble; 120 | 121 | /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 122 | char *string; 123 | } cJSON; 124 | 125 | typedef struct cJSON_Hooks 126 | { 127 | /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ 128 | void *(CJSON_CDECL *malloc_fn)(size_t sz); 129 | void (CJSON_CDECL *free_fn)(void *ptr); 130 | } cJSON_Hooks; 131 | 132 | typedef int cJSON_bool; 133 | 134 | /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. 135 | * This is to prevent stack overflows. */ 136 | #ifndef CJSON_NESTING_LIMIT 137 | #define CJSON_NESTING_LIMIT 1000 138 | #endif 139 | 140 | /* Precision of double variables comparison */ 141 | #ifndef CJSON_DOUBLE_PRECISION 142 | #define CJSON_DOUBLE_PRECISION .0000000000000001 143 | #endif 144 | 145 | /* returns the version of cJSON as a string */ 146 | CJSON_PUBLIC(const char*) cJSON_Version(void); 147 | 148 | /* Supply malloc, realloc and free functions to cJSON */ 149 | CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); 150 | 151 | /* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ 152 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ 153 | CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); 154 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 155 | /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ 156 | CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); 157 | 158 | /* Render a cJSON entity to text for transfer/storage. */ 159 | CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); 160 | /* Render a cJSON entity to text for transfer/storage without any formatting. */ 161 | CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); 162 | /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ 163 | CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); 164 | /* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ 165 | /* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ 166 | CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); 167 | /* Delete a cJSON entity and all subentities. */ 168 | CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); 169 | 170 | /* Returns the number of items in an array (or object). */ 171 | CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); 172 | /* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ 173 | CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); 174 | /* Get item "string" from object. Case insensitive. */ 175 | CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); 176 | CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); 177 | CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); 178 | /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ 179 | CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); 180 | 181 | /* Check if the item is a string and return its valuestring */ 182 | CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); 183 | 184 | /* These functions check the type of an item */ 185 | CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); 186 | CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); 187 | CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); 188 | CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); 189 | CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); 190 | CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); 191 | CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); 192 | CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); 193 | CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); 194 | CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); 195 | 196 | /* These calls create a cJSON item of the appropriate type. */ 197 | CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); 198 | CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); 199 | CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); 200 | CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); 201 | CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); 202 | CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); 203 | /* raw json */ 204 | CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); 205 | CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); 206 | CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); 207 | 208 | /* Create a string where valuestring references a string so 209 | * it will not be freed by cJSON_Delete */ 210 | CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); 211 | /* Create an object/array that only references it's elements so 212 | * they will not be freed by cJSON_Delete */ 213 | CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); 214 | CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); 215 | 216 | /* These utilities create an Array of count items. 217 | * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ 218 | CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); 219 | CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); 220 | CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); 221 | CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); 222 | 223 | /* Append item to the specified array/object. */ 224 | CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); 225 | CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); 226 | /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. 227 | * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before 228 | * writing to `item->string` */ 229 | CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); 230 | /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ 231 | CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 232 | CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); 233 | 234 | /* Remove/Detach items from Arrays/Objects. */ 235 | CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); 236 | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); 237 | CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); 238 | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); 239 | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); 240 | CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); 241 | CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); 242 | 243 | /* Update array items. */ 244 | CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ 245 | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); 246 | CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); 247 | CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 248 | CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); 249 | 250 | /* Duplicate a cJSON item */ 251 | CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); 252 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 253 | * need to be released. With recurse!=0, it will duplicate any children connected to the item. 254 | * The item->next and ->prev pointers are always zero on return from Duplicate. */ 255 | /* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. 256 | * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ 257 | CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); 258 | 259 | /* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. 260 | * The input pointer json cannot point to a read-only address area, such as a string constant, 261 | * but should point to a readable and writable adress area. */ 262 | CJSON_PUBLIC(void) cJSON_Minify(char *json); 263 | 264 | /* Helper functions for creating and adding items to an object at the same time. 265 | * They return the added item or NULL on failure. */ 266 | CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); 267 | CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); 268 | CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); 269 | CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); 270 | CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); 271 | CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); 272 | CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); 273 | CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); 274 | CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); 275 | 276 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 277 | #define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) 278 | /* helper for the cJSON_SetNumberValue macro */ 279 | CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); 280 | #define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) 281 | 282 | /* Macro for iterating over an array or object */ 283 | #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) 284 | 285 | /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ 286 | CJSON_PUBLIC(void *) cJSON_malloc(size_t size); 287 | CJSON_PUBLIC(void) cJSON_free(void *object); 288 | 289 | #ifdef __cplusplus 290 | } 291 | #endif 292 | 293 | #endif 294 | -------------------------------------------------------------------------------- /adapter/cjson/cjson_impl.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cjson_impl.c 3 | * @author sun_chb@126.com 4 | */ 5 | #include "cJSON.h" 6 | #include "cson.h" 7 | #include "string.h" 8 | #include "stdio.h" 9 | 10 | cson_t cjson_impl_object_get(const cson_t object, const char* key){ 11 | return cJSON_GetObjectItem((cJSON*)object, key); 12 | } 13 | 14 | cson_type cjson_impl_typeof(cson_t object){ 15 | switch(((cJSON*)object)->type){ 16 | case cJSON_Invalid: 17 | case cJSON_NULL: 18 | return CSON_NULL; 19 | case cJSON_False: 20 | return CSON_FALSE; 21 | case cJSON_True: 22 | return CSON_TRUE; 23 | case cJSON_Number: 24 | return CSON_REAL; 25 | case cJSON_String: 26 | case cJSON_Raw: 27 | return CSON_STRING; 28 | case cJSON_Array: 29 | return CSON_ARRAY; 30 | case cJSON_Object: 31 | return CSON_OBJECT; 32 | default: 33 | return CSON_NULL; 34 | } 35 | } 36 | 37 | cson_t cjson_impl_loadb(const char *buffer, size_t buflen){ 38 | cson_t ret = NULL; 39 | ret = cJSON_Parse(buffer); 40 | if(!ret){ 41 | printf("parse stop with:%s\n", cJSON_GetErrorPtr()); 42 | } 43 | return ret; 44 | } 45 | 46 | void cjson_impl_decref(cson_t object){ 47 | cJSON_Delete((cJSON*)object); 48 | } 49 | 50 | const char *cjson_impl_string_value(const cson_t object){ 51 | return cJSON_GetStringValue((cJSON*)object); 52 | } 53 | 54 | size_t cjson_impl_string_length(const cson_t object){ 55 | return strlen(cJSON_GetStringValue((cJSON*)object)); 56 | } 57 | 58 | long long cjson_impl_integer_value(const cson_t object){ 59 | return ((cJSON*)object)->valueint; 60 | } 61 | 62 | double cjson_impl_real_value(const cson_t object){ 63 | return ((cJSON*)object)->valuedouble; 64 | } 65 | 66 | char cjson_impl_bool_value(const cson_t object){ 67 | return ((cJSON*)object)->type == cJSON_True; 68 | } 69 | 70 | size_t cjson_impl_array_size(const cson_t object){ 71 | return cJSON_GetArraySize((cJSON*)object); 72 | } 73 | 74 | cson_t cjson_impl_array_get(const cson_t object, size_t index){ 75 | return cJSON_GetArrayItem((cJSON*)object, index); 76 | } 77 | 78 | cson_t cjson_impl_new(){ 79 | return cJSON_CreateObject(); 80 | } 81 | 82 | char* cjson_impl_to_string(cson_t object){ 83 | return cJSON_PrintUnformatted((cJSON*)object); 84 | } 85 | 86 | cson_t cjson_impl_integer(long long val){ 87 | cJSON* tmp = cJSON_CreateNumber(0); 88 | cJSON_SetNumberValue(tmp, val); 89 | return tmp; 90 | } 91 | 92 | cson_t cjson_impl_string(const char* val){ 93 | return cJSON_CreateString(val); 94 | } 95 | 96 | cson_t cjson_impl_bool(char val){ 97 | return cJSON_CreateBool(val); 98 | } 99 | cson_t cjson_impl_real(double val){ 100 | return cJSON_CreateNumber(val); 101 | } 102 | 103 | cson_t cjson_impl_array(){ 104 | return cJSON_CreateArray(); 105 | } 106 | 107 | int cjson_impl_array_add(cson_t array, cson_t obj){ 108 | cJSON_AddItemToArray((cJSON*)array, (cJSON*)obj); 109 | return 0; 110 | } 111 | 112 | int cjson_impl_object_set_new(cson_t rootObj, const char* field, cson_t obj){ 113 | cJSON_AddItemToObject((cJSON*)rootObj, field, (cJSON*)obj); 114 | return 0; 115 | } 116 | 117 | cson_interface csomImpl = { 118 | cjson_impl_object_get, 119 | cjson_impl_typeof, 120 | cjson_impl_loadb, 121 | cjson_impl_decref, 122 | cjson_impl_string_value, 123 | cjson_impl_string_length, 124 | cjson_impl_integer_value, 125 | cjson_impl_real_value, 126 | cjson_impl_bool_value, 127 | cjson_impl_array_size, 128 | cjson_impl_array_get, 129 | cjson_impl_new, 130 | cjson_impl_to_string, 131 | cjson_impl_integer, 132 | cjson_impl_string, 133 | cjson_impl_bool, 134 | cjson_impl_real, 135 | cjson_impl_array, 136 | cjson_impl_array_add, 137 | cjson_impl_object_set_new 138 | }; 139 | -------------------------------------------------------------------------------- /adapter/jansson/jansson_impl.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file jansson_impl.c 3 | * @author sun_chb@126.com 4 | */ 5 | #include "cson.h" 6 | #include "jansson.h" 7 | #include "stdio.h" 8 | 9 | cson_t jansson_impl_object_get(const cson_t object, const char* key){ 10 | return json_object_get((json_t*)object, key); 11 | } 12 | 13 | cson_type jansson_impl_typeof(cson_t object){ 14 | return (cson_type)json_typeof((json_t*)object); 15 | } 16 | 17 | cson_t jansson_impl_loadb(const char *buffer, size_t buflen){ 18 | cson_t ret = NULL; 19 | json_error_t err; 20 | 21 | ret = json_loadb(buffer, buflen, JSON_DECODE_ANY, &err); 22 | 23 | if(!ret){ 24 | printf("line:%d,column:%d,pos:%d,source:%s,text:%s\n", 25 | err.line, 26 | err.column, 27 | err.position, 28 | err.source, 29 | err.text); 30 | } 31 | return ret; 32 | } 33 | 34 | void jansson_impl_decref(cson_t object){ 35 | json_decref((json_t*)object); 36 | } 37 | 38 | const char *jansson_impl_string_value(const cson_t object){ 39 | return json_string_value((json_t*)object); 40 | } 41 | 42 | size_t jansson_impl_string_length(const cson_t object){ 43 | return json_string_length((json_t*)object); 44 | } 45 | 46 | long long jansson_impl_integer_value(const cson_t object){ 47 | return json_integer_value((json_t*)object); 48 | } 49 | 50 | double jansson_impl_real_value(const cson_t object){ 51 | return json_real_value((json_t*)object); 52 | } 53 | 54 | char jansson_impl_bool_value(const cson_t object){ 55 | return json_boolean_value((json_t*)object); 56 | } 57 | 58 | size_t jansson_impl_array_size(const cson_t object){ 59 | return json_array_size((json_t*)object); 60 | } 61 | 62 | cson_t jansson_impl_array_get(const cson_t object, size_t index){ 63 | return json_array_get((json_t*)object, index); 64 | } 65 | 66 | cson_t jansson_impl_new(){ 67 | return json_object(); 68 | } 69 | 70 | char* jansson_impl_to_string(cson_t object){ 71 | return json_dumps((json_t*)object, JSON_COMPACT | JSON_PRESERVE_ORDER); 72 | } 73 | 74 | cson_t jansson_impl_integer(long long val){ 75 | return json_integer(val); 76 | } 77 | 78 | cson_t jansson_impl_string(const char* val){ 79 | return json_string(val); 80 | } 81 | 82 | cson_t jansson_impl_bool(char val){ 83 | return json_boolean(val); 84 | } 85 | 86 | cson_t jansson_impl_real(double val){ 87 | return json_real(val); 88 | } 89 | 90 | cson_t jansson_impl_array(){ 91 | return json_array(); 92 | } 93 | 94 | int jansson_impl_array_add(cson_t array, cson_t obj){ 95 | return json_array_append_new((json_t*)array, (json_t*)obj); 96 | } 97 | 98 | int jansson_impl_object_set_new(cson_t rootObj, const char* field, cson_t obj){ 99 | return json_object_set_new((json_t*)rootObj, field, (json_t*)obj); 100 | } 101 | 102 | cson_interface csomImpl = { 103 | jansson_impl_object_get, 104 | jansson_impl_typeof, 105 | jansson_impl_loadb, 106 | jansson_impl_decref, 107 | jansson_impl_string_value, 108 | jansson_impl_string_length, 109 | jansson_impl_integer_value, 110 | jansson_impl_real_value, 111 | jansson_impl_bool_value, 112 | jansson_impl_array_size, 113 | jansson_impl_array_get, 114 | jansson_impl_new, 115 | jansson_impl_to_string, 116 | jansson_impl_integer, 117 | jansson_impl_string, 118 | jansson_impl_bool, 119 | jansson_impl_real, 120 | jansson_impl_array, 121 | jansson_impl_array_add, 122 | jansson_impl_object_set_new 123 | }; 124 | -------------------------------------------------------------------------------- /demo/Makefile: -------------------------------------------------------------------------------- 1 | INC += -I../3rd/inc 2 | INC += -I../inc 3 | LIB_PATH += -L../3rd/lib 4 | LIB_PATH += -L../output 5 | CC=gcc 6 | test:test.c main.c 7 | @$(CC) $(INC) $(LIB_PATH) -g -o test test.c test2.c main.c -Wno-int-conversion -lcson -ljansson 8 | clean: 9 | @rm -rf test 10 | -------------------------------------------------------------------------------- /demo/main.c: -------------------------------------------------------------------------------- 1 | extern void test1(); 2 | extern void test2(); 3 | 4 | #include "cson.h" 5 | #include "stdio.h" 6 | 7 | int main() 8 | { 9 | test1(); 10 | test2(); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /demo/test.c: -------------------------------------------------------------------------------- 1 | #include "cson.h" 2 | #include "stdio.h" 3 | #include "string.h" 4 | #include "stdlib.h" 5 | 6 | #include "assert.h" 7 | #include "math.h" 8 | 9 | #define CHECK_STRING(a, b) assert(strcmp(a, b) == 0) 10 | #define CHECK_NUMBER(a, b) assert(a == b) 11 | #define CHECK_REAL(a, b) assert(fabs(a-b) <= 1e-6) 12 | /** 13 | * 该示例会使用cson解析如下所示播放列表。 14 | * 15 | { 16 | "name":"jay zhou", 17 | "creater":"dahuaxia", 18 | "songNum":2, 19 | "songList":[ 20 | { 21 | "songName":"qilixiang", 22 | "signerName":"jay zhou", 23 | "albumName":"qilixiang", 24 | "url":"www.kugou.com", 25 | "duration":200, 26 | "paid":false, 27 | "price":6.6600000000000001, 28 | "lyricNum":2, 29 | "lyric":[ 30 | { 31 | "time":1, 32 | "text":"Sparrow outside the window" 33 | }, 34 | { 35 | "time":10, 36 | "text":"Multi mouth on the pole" 37 | } 38 | ], 39 | "key":[ 40 | 1234, 41 | 5678, 42 | 9876 43 | ] 44 | }, 45 | { 46 | "songName":"dongfengpo", 47 | "signerName":"jay zhou", 48 | "albumName":"dongfengpo", 49 | "url":"music.qq.com", 50 | "duration":180, 51 | "paid":true, 52 | "price":0.88, 53 | "lyricNum":2, 54 | "lyric":[ 55 | { 56 | "time":10, 57 | "text":"A sad parting, standing alone in the window" 58 | }, 59 | { 60 | "time":20, 61 | "text":"I'm behind the door pretending you're not gone" 62 | } 63 | ], 64 | "key":[ 65 | 1111, 66 | 2222, 67 | 3333 68 | ] 69 | } 70 | ], 71 | "extData":{ 72 | "a":999, 73 | "b":1.05 74 | } 75 | } 76 | */ 77 | 78 | /** 79 | * 1)首先我们需要定义与上面json相对应的数据结构。于是有了@PlayList、@ExtData、@SongInfo、@Lyric。 80 | * 即使不实用cson,想要解析json,通常你也需要这么做。 81 | * 82 | * 注意:结构体属性名需与json中字段名一致; 83 | * 注意:当某个字段在json中被定义为数组时,那么该字段在结构体中要被声名为指针,并且增加数组size的字段。 84 | * 85 | * 2)为了C语言能够像java中通过反射来操作结构体中的属性,我们需要先为每个结构体定义一个用于查找结构体属性的“反射表”, 86 | * 即play_list_ref_tbl,ext_data_ref_tbl,song_ref_tbl,lyric_ref_tbl。 87 | * 有了这个反射表,我们可以迭代访问数组元素。不仅可以帮助我们完成json解析,当我们想要输出对象各属性值、或是释放 88 | * 指针指向的堆内存时也很有用。 89 | * 90 | * TODO:目前反射表的结构有些复杂,虽然提供了宏定义让它用来稍稍方便一些。需要对该结构做出优化。 91 | * 92 | * 3)正确的完成上面两步,解析工作其实基本上就要完成了。只要再调用csonJsonStr2Struct,所有的属性就都会正确的赋值到结构体。 93 | * 94 | */ 95 | 96 | 97 | /* 98 | Step1:定义与json相对应的数据结构 99 | */ 100 | typedef struct { 101 | int time; 102 | char* text; 103 | } Lyric; 104 | 105 | typedef struct { 106 | char* songName; 107 | char* signerName; 108 | char* albumName; 109 | char* url; 110 | int duration; 111 | int paid; 112 | double price; 113 | size_t lyricNum; 114 | Lyric* lyric; 115 | size_t keyNum; 116 | int* key; 117 | size_t strNum; 118 | char** strList; 119 | } SongInfo; 120 | 121 | typedef struct { 122 | int a; 123 | double b; 124 | } ExtData; 125 | 126 | typedef struct { 127 | char* name; 128 | char* creater; 129 | size_t songNum; 130 | SongInfo* songList; 131 | ExtData extData; 132 | } PlayList; 133 | 134 | /* 135 | Step2:定义数据结构的反射表 136 | */ 137 | reflect_item_t lyric_ref_tbl[] = { 138 | _property_int(Lyric, time), 139 | _property_string(Lyric, text), 140 | _property_end() 141 | }; 142 | 143 | reflect_item_t song_ref_tbl[] = { 144 | _property_string(SongInfo, songName), 145 | _property_string(SongInfo, signerName), 146 | _property_string(SongInfo, albumName), 147 | _property_string(SongInfo, url), 148 | _property_int(SongInfo, duration), 149 | _property_bool(SongInfo, paid), 150 | _property_real(SongInfo, price), 151 | _property_int_ex(SongInfo, lyricNum, _ex_args_all), 152 | _property_array_object(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum), 153 | _property_int_ex(SongInfo, keyNum, _ex_args_all), 154 | _property_array_int(SongInfo, key, int, keyNum), 155 | _property_int_ex(SongInfo, strNum, _ex_args_all), 156 | _property_array_string(SongInfo, strList, char*, strNum), 157 | _property_end() 158 | }; 159 | 160 | reflect_item_t ext_data_ref_tbl[] = { 161 | _property_int(ExtData, a), 162 | _property_real(ExtData, b), 163 | _property_end() 164 | }; 165 | 166 | reflect_item_t play_list_ref_tbl[] = { 167 | _property_string(PlayList, name), 168 | _property_string(PlayList, creater), 169 | _property_int_ex(PlayList, songNum, _ex_args_all), 170 | _property_array_object(PlayList, songList, song_ref_tbl, SongInfo, songNum), 171 | _property_obj(PlayList, extData, ext_data_ref_tbl), 172 | _property_end() 173 | }; 174 | 175 | static void printPlayList(PlayList* list); 176 | static void freePlayList(PlayList* list); 177 | 178 | const static char* jStr = "{\"name\":\"jay zhou\",\"creater\":\"dahuaxia\",\"songList\":[{\"songName\":\"qilixiang\",\"signerName\":\"jay zhou\",\"albumName\":\"qilixiang\",\"url\":\"www.kugou.com\",\"duration\":20093999939292928292234.1,\"paid\":false,\"price\":6.66,\"lyric\":[{\"time\":1,\"text\":\"Sparrow outside the window\"},{\"time\":10,\"text\":\"Multi mouth on the pole\"}],\"key\":[1111,2222,3333]},{\"songName\":\"dongfengpo\",\"signerName\":\"jay zhou\",\"albumName\":\"dongfengpo\",\"url\":\"music.qq.com\",\"duration\":180.9,\"paid\":true,\"price\":0.88,\"lyric\":[{\"time\":10,\"text\":\"A sad parting, standing alone in the window\"},{\"time\":20,\"text\":\"I'm behind the door pretending you're not gone\"}],\"key\":[1234,5678,9876],\"strList\":[\"abcd\",\"efgh\",\"ijkl\"]}],\"extData\":{\"a\":999,\"b\":1}}"; 179 | 180 | static void checkResult(PlayList* playList, char* jstrOutput); 181 | /* 182 | Step3:调用csonJsonStr2Struct/csonStruct2JsonStr实现反序列化和序列化 183 | */ 184 | void test1() 185 | { 186 | printf("=========================================\n"); 187 | printf("\t\tRunning %s\n", __FUNCTION__); 188 | printf("=========================================\n"); 189 | PlayList playList; 190 | memset(&playList, 0, sizeof(playList)); 191 | 192 | /* string to struct */ 193 | int ret = csonJsonStr2Struct(jStr, &playList, play_list_ref_tbl); 194 | CHECK_NUMBER(ret, 0); 195 | printf("decode ret=%d\n", ret); 196 | /* test print */ 197 | //csonPrintProperty(&playList, play_list_ref_tbl); 198 | 199 | char* jstrOutput; 200 | ret = csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl); 201 | CHECK_NUMBER(ret, 0); 202 | printf("encode ret=%d\nJson:%s\n", ret, jstrOutput); 203 | 204 | /*assert check*/ 205 | checkResult(&playList, jstrOutput); 206 | 207 | free(jstrOutput); 208 | csonFreePointer(&playList, play_list_ref_tbl); 209 | 210 | printf("Successed %s.\n", __FUNCTION__); 211 | } 212 | 213 | 214 | void checkResult(PlayList* playList, char* jstrOutput){ 215 | const char* encodeTest = "{\"name\":\"jay zhou\",\"creater\":\"dahuaxia\",\"songList\":[{\"songName\":\"qilixiang\",\"signerName\":\"jay zhou\",\"albumName\":\"qilixiang\",\"url\":\"www.kugou.com\",\"duration\":0,\"paid\":false,\"price\":6.66,\"lyric\":[{\"time\":1,\"text\":\"Sparrow outside the window\"},{\"time\":10,\"text\":\"Multi mouth on the pole\"}],\"key\":[1111,2222,3333]},{\"songName\":\"dongfengpo\",\"signerName\":\"jay zhou\",\"albumName\":\"dongfengpo\",\"url\":\"music.qq.com\",\"duration\":180,\"paid\":true,\"price\":0.88,\"lyric\":[{\"time\":10,\"text\":\"A sad parting, standing alone in the window\"},{\"time\":20,\"text\":\"I'm behind the door pretending you're not gone\"}],\"key\":[1234,5678,9876],\"strList\":[\"abcd\",\"efgh\",\"ijkl\"]}],\"extData\":{\"a\":999,\"b\":1}}"; 216 | 217 | /* assert test */ 218 | CHECK_STRING(playList->name, "jay zhou"); 219 | CHECK_STRING(playList->creater, "dahuaxia"); 220 | CHECK_NUMBER(playList->songNum, 2); 221 | CHECK_STRING(playList->songList[0].songName, "qilixiang"); 222 | CHECK_STRING(playList->songList[0].signerName, "jay zhou"); 223 | CHECK_STRING(playList->songList[0].albumName, "qilixiang"); 224 | CHECK_STRING(playList->songList[0].url, "www.kugou.com"); 225 | CHECK_NUMBER(playList->songList[0].duration, 0); 226 | CHECK_NUMBER(playList->songList[0].paid, 0); 227 | CHECK_REAL(playList->songList[0].price, 6.66); 228 | CHECK_NUMBER(playList->songList[0].lyricNum, 2); 229 | CHECK_NUMBER(playList->songList[0].lyric[0].time, 1); 230 | CHECK_STRING(playList->songList[0].lyric[0].text, "Sparrow outside the window"); 231 | CHECK_NUMBER(playList->songList[0].lyric[1].time, 10); 232 | CHECK_STRING(playList->songList[0].lyric[1].text, "Multi mouth on the pole"); 233 | CHECK_NUMBER(playList->songList[0].keyNum, 3); 234 | CHECK_NUMBER(playList->songList[0].key[0], 1111); 235 | CHECK_NUMBER(playList->songList[0].key[1], 2222); 236 | CHECK_NUMBER(playList->songList[0].key[2], 3333); 237 | CHECK_NUMBER(playList->songList[0].strNum, 0); 238 | 239 | CHECK_STRING(playList->songList[1].songName, "dongfengpo"); 240 | CHECK_STRING(playList->songList[1].signerName, "jay zhou"); 241 | CHECK_STRING(playList->songList[1].albumName, "dongfengpo"); 242 | CHECK_STRING(playList->songList[1].url, "music.qq.com"); 243 | CHECK_NUMBER(playList->songList[1].duration, 180); 244 | CHECK_NUMBER(playList->songList[1].paid, 1); 245 | CHECK_REAL(playList->songList[1].price, 0.88); 246 | CHECK_NUMBER(playList->songList[1].lyricNum, 2); 247 | CHECK_NUMBER(playList->songList[1].lyric[0].time, 10); 248 | CHECK_STRING(playList->songList[1].lyric[0].text, "A sad parting, standing alone in the window"); 249 | CHECK_NUMBER(playList->songList[1].lyric[1].time, 20); 250 | CHECK_STRING(playList->songList[1].lyric[1].text, "I'm behind the door pretending you're not gone"); 251 | CHECK_NUMBER(playList->songList[1].keyNum, 3); 252 | CHECK_NUMBER(playList->songList[1].key[0], 1234); 253 | CHECK_NUMBER(playList->songList[1].key[1], 5678); 254 | CHECK_NUMBER(playList->songList[1].key[2], 9876); 255 | CHECK_NUMBER(playList->songList[1].strNum, 3); 256 | CHECK_STRING(playList->songList[1].strList[0], "abcd"); 257 | CHECK_STRING(playList->songList[1].strList[1], "efgh"); 258 | CHECK_STRING(playList->songList[1].strList[2], "ijkl"); 259 | CHECK_NUMBER(playList->extData.a, 999); 260 | CHECK_REAL(playList->extData.b, 1); 261 | 262 | //It is difficult to predict the output due to the accuracy problem. 263 | //CHECK_STRING(jstrOutput, encodeTest); 264 | } -------------------------------------------------------------------------------- /demo/test2.c: -------------------------------------------------------------------------------- 1 | #include "cson.h" 2 | #include "stdio.h" 3 | #include "stdlib.h" 4 | #include "string.h" 5 | 6 | 7 | #include "assert.h" 8 | #include "math.h" 9 | 10 | #define CHECK_STRING(a, b) assert(strcmp(a, b) == 0) 11 | #define CHECK_NUMBER(a, b) assert(a == b) 12 | #define CHECK_REAL(a, b) assert(fabs(a-b) <= 1e-6) 13 | 14 | typedef struct { 15 | char* name; 16 | char* jump_url; 17 | } ClassInfoChild; 18 | 19 | typedef struct { 20 | int has_child; 21 | char* icon; 22 | int id; 23 | char* name; 24 | char childrenNum; 25 | ClassInfoChild* children; 26 | } ClassInfo; 27 | 28 | typedef struct { 29 | long long timestamp; 30 | int infoNum; 31 | ClassInfo* info; 32 | } Data; 33 | 34 | typedef struct { 35 | int status; 36 | Data data; 37 | int errcode; 38 | } Response; 39 | 40 | reflect_item_t ClassInfoChildTbl[] = { 41 | _property_string(ClassInfoChild, name), 42 | _property_string(ClassInfoChild, jump_url), 43 | _property_end() 44 | }; 45 | 46 | reflect_item_t ClassInfoTbl[] = { 47 | _property_int(ClassInfo, has_child), 48 | _property_string(ClassInfo, icon), 49 | _property_int(ClassInfo, id), 50 | _property_string(ClassInfo, name), 51 | _property_int_ex(ClassInfo, childrenNum, _ex_args_all), 52 | _property_array_object(ClassInfo, children, ClassInfoChildTbl, ClassInfoChild, childrenNum), 53 | _property_end() 54 | }; 55 | 56 | reflect_item_t DataTbl[] = { 57 | _property_int(Data, timestamp), 58 | _property_int_ex(Data, infoNum, _ex_args_all), 59 | _property_array_object(Data, info, ClassInfoTbl, ClassInfo, infoNum), 60 | _property_end() 61 | }; 62 | 63 | reflect_item_t ResponseTbl[] = { 64 | _property_int(Response, status), 65 | _property_obj(Response, data, DataTbl), 66 | _property_int(Response, errcode), 67 | _property_end() 68 | }; 69 | 70 | const static char* jStr = "{\"status\":1,\"error\":\"\",\"data\":{\"timestamp\":1579069151,\"info\":[{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172444711866.png\",\"id\":153,\"children\":[{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F1\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20190402/20190402165900910180.png\",\"id\":185,\"name\":\"DJ专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1hFCsBvW_1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150825/20150825145251513968.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F45\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711142859901220.png\",\"id\":1401,\"name\":\"抖音专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F3\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20190402/20190402165839822861.png\",\"id\":227,\"name\":\"儿童专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1xNKsBmb_1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":1,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150819/20150819142111579284.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F23\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110341142930.png\",\"id\":781,\"name\":\"网络专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F9\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110304370142.png\",\"id\":405,\"name\":\"车载专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1TJKsB_K_1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20151020/20151020185634232826.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F11\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110531714649.png\",\"id\":483,\"name\":\"广场舞专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T13ebsBgC_1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20151030/20151030100347338896.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F17\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110434661130.png\",\"id\":439,\"name\":\"轻音乐专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1jTJsBmZT1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20151026/20151026102137944162.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F19\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110403270402.png\",\"id\":721,\"name\":\"情歌专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F7\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110649518903.png\",\"id\":363,\"name\":\"国风专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1XJYsBXWj1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":1,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20151019/20151019195642566658.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20160119/20160119175107905652.png\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F27\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20190417/20190417104751432731.png\",\"id\":993,\"name\":\"电音专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F29\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191107/20191107150209613377.png\",\"id\":1047,\"name\":\"欧美专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F5\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101111143849486.png\",\"id\":381,\"name\":\"ACG专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1OdWsByYT1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20151023/20151023175903317815.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F15\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181106/20181106162159569853.png\",\"id\":155,\"name\":\"影视专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1xzKsBvWT1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150916/20150916115630236448.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F25\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110659435688.png\",\"id\":803,\"name\":\"戏曲专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F13\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181106/20181106162128954559.png\",\"id\":625,\"name\":\"粤剧专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F31\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191115/20191115142149416417.png\",\"id\":1031,\"name\":\"韩流专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"专区\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104103209217784.png\",\"id\":2005,\"children\":[{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2131,\"name\":\"伤感专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112110650706413.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2137,\"name\":\"安静专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112110813847387.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2143,\"name\":\"对抗抑郁专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112114053306456.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2149,\"name\":\"轻松专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112114115681652.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2155,\"name\":\"激情专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112114229679116.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2161,\"name\":\"甜蜜专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112114455522172.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2167,\"name\":\"开心专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112114657687089.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2173,\"name\":\"想念专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112141710521727.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2179,\"name\":\"疗伤专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191112/20191112141926500890.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"心情\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172455112096.png\",\"id\":1263,\"children\":[{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1409,\"name\":\"官方歌单\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190701/20190701141020364105.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F65\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2365,\"name\":\"重返2010专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":1,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":277,\"name\":\"佛乐专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1eFVsBXZT1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150916/20150916115656566037.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191113/20191113230926826063.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2findex.html%23%2fmobile%2fhome%2f37\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181106/20181106162140754053.png\",\"id\":209,\"name\":\"综艺专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1zXKsBvA_1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150916/20150916115609586448.png\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F35\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181106/20181106162058103005.png\",\"id\":1243,\"name\":\"首发专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F33\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101111200228559.png\",\"id\":1091,\"name\":\"音乐人专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":789,\"name\":\"古典乐专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190626/20190626152411750201.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F21\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110554351882.png\",\"id\":739,\"name\":\"HiFi专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1215,\"name\":\"英语学习专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190626/20190626152421673705.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F69\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1269,\"name\":\"2019年终专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/387f9f19bffe870e3c722d2958661856.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20181229/20181229140823201468.jpg\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191226/20191226172357900648.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F39\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20190328/20190328212216110068.png\",\"id\":1297,\"name\":\"有声电台\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20190812/20190812102122694905.png\",\"id\":1387,\"name\":\"Urban专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191118/20191118163905185498.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1415,\"name\":\"入驻厂牌专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190819/20190819111049128125.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F71\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2389,\"name\":\"游戏专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F63\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2395,\"name\":\"说唱专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":1,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2029,\"name\":\"冬天听什么专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191107/20191107101634149569.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"特色\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104103220446249.png\",\"id\":2003,\"children\":[{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181101/20181101110630241664.png\",\"id\":279,\"name\":\"运动健身专区\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1fFYsBX_j1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150916/20150916115717647762.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191202/20191202163552854924.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2013,\"name\":\"睡前专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122151057972712.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2247,\"name\":\"店铺音乐专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122151034810296.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2253,\"name\":\"打游戏专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122151254643206.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2259,\"name\":\"K歌必唱专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122151421773216.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2265,\"name\":\"开车专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122151558972937.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2271,\"name\":\"咖啡馆专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122151837262100.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2277,\"name\":\"蹦迪专用专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122152028593609.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2289,\"name\":\"校园专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191122/20191122152405265191.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"场景\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104103232420148.png\",\"id\":2007,\"children\":[{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F51\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1555,\"name\":\"经典老歌专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191202/20191202141928720121.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F73\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2407,\"name\":\"春节专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2055,\"name\":\"成名曲专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111174249287596.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2061,\"name\":\"舞曲专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111174452186715.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2067,\"name\":\"儿歌专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111174906536922.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2073,\"name\":\"新歌推荐专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111175047676679.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2079,\"name\":\"情歌对唱专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111175209162382.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2085,\"name\":\"励志专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111175327714784.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2091,\"name\":\"军旅红歌专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111175550208859.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2097,\"name\":\"铃声专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111180946152637.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2103,\"name\":\"神曲专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111181117318818.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2109,\"name\":\"城市风情专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111182647106360.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2115,\"name\":\"会员专属专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111182803792312.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2121,\"name\":\"BGM专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191111/20191111183127748172.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"主题\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172345416784.png\",\"id\":32,\"children\":[{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":33,\"name\":\"70后\",\"special_tag_id\":13,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1O9bjBKDT1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150415/20150415164642347845.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191115/20191115170921589845.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":34,\"name\":\"80后\",\"special_tag_id\":14,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1kMCjB4dj1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150415/20150415164652136718.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191115/20191115170927143738.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":35,\"name\":\"90后\",\"special_tag_id\":76,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1gnCjBbKT1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20160215/20160215094154552929.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191115/20191115170935539112.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":96,\"name\":\"00后\",\"special_tag_id\":571,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1d7KQByhb1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150513/20150513180053392639.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191115/20191115170942262316.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"年代\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191202/20191202161746384633.png\",\"id\":2009,\"children\":[{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2195,\"name\":\"国语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120163611415408.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2201,\"name\":\"粤语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120163743863149.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2207,\"name\":\"英语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120163937144325.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2213,\"name\":\"韩语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120164217668731.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2219,\"name\":\"日语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120164440825780.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2225,\"name\":\"法语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120164814523281.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2231,\"name\":\"闽南语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120164945463716.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":2237,\"name\":\"客家语专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120165207596701.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1323,\"name\":\"小语种专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191202/20191202162147271334.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"语言\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104102344527371.png\",\"id\":1599,\"children\":[{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1601&subname=%E6%B5%81%E8%A1%8C%E4%B8%93%E5%8C%BA\",\"album_tag_id\":9,\"icon\":\"\",\"id\":1601,\"name\":\"流行专区\",\"special_tag_id\":9,\"bannerurl\":\"\",\"song_tag_id\":882,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120171432358307.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Pop\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1615&subname=%E7%94%B5%E5%AD%90%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1615,\"name\":\"电子专区\",\"special_tag_id\":33,\"bannerurl\":\"\",\"song_tag_id\":595,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120174623547423.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Electronic\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1611&subname=%E6%91%87%E6%BB%9A%E4%B8%93%E5%8C%BA\",\"album_tag_id\":27,\"icon\":\"\",\"id\":1611,\"name\":\"摇滚专区\",\"special_tag_id\":27,\"bannerurl\":\"\",\"song_tag_id\":883,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20191101/20191101100648571107.jpg\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120181659501645.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Rock\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1613&subname=%E7%BA%AF%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1613,\"name\":\"纯音乐专区\",\"special_tag_id\":34,\"bannerurl\":\"\",\"song_tag_id\":960,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120181707580363.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"PureMusic\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1707&subname=%E5%9B%BD%E9%A3%8E%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1707,\"name\":\"国风音乐专区\",\"special_tag_id\":574,\"bannerurl\":\"\",\"song_tag_id\":1621,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120181744220526.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"GuoFeng\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1715&subname=%E5%98%BB%E5%93%88%E4%B8%93%E5%8C%BA\",\"album_tag_id\":31,\"icon\":\"\",\"id\":1715,\"name\":\"嘻哈专区\",\"special_tag_id\":31,\"bannerurl\":\"\",\"song_tag_id\":588,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120183103443876.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"HipHop\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1743&subname=R&B/Soul%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1743,\"name\":\"R&BSoul专区\",\"special_tag_id\":30,\"bannerurl\":\"\",\"song_tag_id\":30,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120183438462155.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"R&BSoul\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1761&subname=%E6%B0%91%E8%B0%A3%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1761,\"name\":\"民谣专区\",\"special_tag_id\":83,\"bannerurl\":\"\",\"song_tag_id\":590,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120182114164802.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Folk\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1775&subname=DJ%E6%AD%8C%E6%9B%B2%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1775,\"name\":\"DJ歌曲专区\",\"special_tag_id\":17,\"bannerurl\":\"\",\"song_tag_id\":961,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120182713572393.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"DJ\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1783&subname=%E5%8F%A4%E5%85%B8%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1783,\"name\":\"古典专区\",\"special_tag_id\":28,\"bannerurl\":\"\",\"song_tag_id\":28,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120184023344633.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Classical\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1807&subname=%E4%B8%96%E7%95%8C%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1807,\"name\":\"世界音乐专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":1370,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191115/20191115163459485041.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"WorldMusic\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1833&subname=%E4%B9%A1%E6%9D%91%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1833,\"name\":\"乡村专区\",\"special_tag_id\":15,\"bannerurl\":\"\",\"song_tag_id\":589,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120184345386442.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Country\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1849&subname=%E7%88%B5%E5%A3%AB%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1849,\"name\":\"爵士专区\",\"special_tag_id\":32,\"bannerurl\":\"\",\"song_tag_id\":591,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120184430385134.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Jazz\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1883&subname=%E5%AE%9E%E9%AA%8C%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1883,\"name\":\"实验音乐专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":1508,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120184446897622.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Experimental\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1895&subname=%E6%8B%89%E4%B8%81%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1895,\"name\":\"拉丁专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":636,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104102058253387.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Latin\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1901&subname=%E9%87%91%E5%B1%9E%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1901,\"name\":\"金属专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":964,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120185812621087.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Metal\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1915&subname=%E6%9C%8B%E5%85%8B%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1915,\"name\":\"朋克专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":981,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104101747389850.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Punk\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1917&subname=%E9%9B%B7%E9%AC%BC%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1917,\"name\":\"雷鬼专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":92,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104101740553832.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Reggae\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1925&subname=%E5%B8%83%E9%B2%81%E6%96%AF%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1925,\"name\":\"布鲁斯专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":94,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120185852698739.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"Blues\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1921&subname=ACG%E6%AD%8C%E6%9B%B2%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1921,\"name\":\"ACG歌曲专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":77,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120190020600949.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"ACG\",\"description\":\"\"},{\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1923&subname=%E4%B8%AD%E5%9B%BD%E7%89%B9%E8%89%B2%E4%B8%93%E5%8C%BA\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1923,\"name\":\"中国特色专区\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":1539,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191120/20191120172611173213.jpg\",\"is_new\":0,\"has_child\":1,\"theme\":1,\"subtitle\":\"ChineseCharacteristic\",\"description\":\"\"}],\"name\":\"风格\",\"subtitle\":\"\",\"description\":\"\"},{\"has_child\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172408696210.png\",\"id\":58,\"children\":[{\"jump_url\":\"\",\"album_tag_id\":727,\"icon\":\"\",\"id\":513,\"name\":\"古筝\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1VTKQBjKv1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20151030/20151030153435669683.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711161915866564.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":722,\"icon\":\"\",\"id\":85,\"name\":\"钢琴\",\"special_tag_id\":16,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1qeYQB5Cj1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150525/20150525184305921626.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711161925785009.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":728,\"icon\":\"\",\"id\":87,\"name\":\"笛子\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1fwYQBjDj1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150525/20150525184610645366.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711161934440425.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":729,\"icon\":\"\",\"id\":88,\"name\":\"二胡\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T13nbjB4KT1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150525/20150525184645692027.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711161941249461.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":723,\"icon\":\"\",\"id\":89,\"name\":\"吉他\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T179KjB4L_1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150525/20150525184751644907.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711161954746142.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":724,\"icon\":\"\",\"id\":90,\"name\":\"萨克斯\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1_nCjBgLg1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150525/20150525185050912141.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711162001984006.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":726,\"icon\":\"\",\"id\":91,\"name\":\"八音盒\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T18eYQBXCQ1RCvBVdK.png\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150525/20150525185012650817.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711162012632790.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":725,\"icon\":\"\",\"id\":92,\"name\":\"小提琴\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T1tg_jBsYT1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20150525/20150525184937467712.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711162040822512.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":854,\"icon\":\"\",\"id\":1097,\"name\":\"葫芦丝\",\"special_tag_id\":0,\"bannerurl\":\"http://imge.kugou.com/v2/mobile_class_banner/{size}/T158hkBmxv1RCvBVdK.jpg\",\"song_tag_id\":0,\"is_hot\":0,\"imgurl\":\"http://imge.kugou.com/mcommon/{size}/20170314/20170314160138927434.png\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20190711/20190711162047231895.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"},{\"jump_url\":\"\",\"album_tag_id\":0,\"icon\":\"\",\"id\":1565,\"name\":\"唢呐\",\"special_tag_id\":0,\"bannerurl\":\"\",\"song_tag_id\":185,\"is_hot\":0,\"imgurl\":\"\",\"banner_hd\":\"http://imge.kugou.com/mcommon/{size}/20191014/20191014140609433424.jpg\",\"is_new\":0,\"has_child\":0,\"theme\":1,\"subtitle\":\"\",\"description\":\"\"}],\"name\":\"乐器\",\"subtitle\":\"\",\"description\":\"\"}]},\"errcode\":0}"; 71 | 72 | const char* encodeTest = "{\"status\":1,\"data\":{\"timestamp\":1579069151,\"info\":[{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172444711866.png\",\"id\":153,\"name\":\"专区\",\"children\":[{\"name\":\"DJ专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F1\"},{\"name\":\"抖音专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F45\"},{\"name\":\"儿童专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F3\"},{\"name\":\"网络专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F23\"},{\"name\":\"车载专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F9\"},{\"name\":\"广场舞专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F11\"},{\"name\":\"轻音乐专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F17\"},{\"name\":\"情歌专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F19\"},{\"name\":\"国风专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F7\"},{\"name\":\"电音专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F27\"},{\"name\":\"欧美专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F29\"},{\"name\":\"ACG专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F5\"},{\"name\":\"影视专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F15\"},{\"name\":\"戏曲专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F25\"},{\"name\":\"粤剧专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F13\"},{\"name\":\"韩流专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F31\"}]},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104103209217784.png\",\"id\":2005,\"name\":\"心情\",\"children\":[{\"name\":\"伤感专区\",\"jump_url\":\"\"},{\"name\":\"安静专区\",\"jump_url\":\"\"},{\"name\":\"对抗抑郁专区\",\"jump_url\":\"\"},{\"name\":\"轻松专区\",\"jump_url\":\"\"},{\"name\":\"激情专区\",\"jump_url\":\"\"},{\"name\":\"甜蜜专区\",\"jump_url\":\"\"},{\"name\":\"开心专区\",\"jump_url\":\"\"},{\"name\":\"想念专区\",\"jump_url\":\"\"},{\"name\":\"疗伤专区\",\"jump_url\":\"\"}]},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172455112096.png\",\"id\":1263,\"name\":\"特色\",\"children\":[{\"name\":\"官方歌单\",\"jump_url\":\"\"},{\"name\":\"重返2010专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F65\"},{\"name\":\"佛乐专区\",\"jump_url\":\"\"},{\"name\":\"综艺专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2findex.html%23%2fmobile%2fhome%2f37\"},{\"name\":\"首发专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F35\"},{\"name\":\"音乐人专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F33\"},{\"name\":\"古典乐专区\",\"jump_url\":\"\"},{\"name\":\"HiFi专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F21\"},{\"name\":\"英语学习专区\",\"jump_url\":\"\"},{\"name\":\"2019年终专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F69\"},{\"name\":\"有声电台\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F39\"},{\"name\":\"Urban专区\",\"jump_url\":\"\"},{\"name\":\"入驻厂牌专区\",\"jump_url\":\"\"},{\"name\":\"游戏专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F71\"},{\"name\":\"说唱专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F63\"},{\"name\":\"冬天听什么专区\",\"jump_url\":\"\"}]},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104103220446249.png\",\"id\":2003,\"name\":\"场景\",\"children\":[{\"name\":\"运动健身专区\",\"jump_url\":\"\"},{\"name\":\"睡前专区\",\"jump_url\":\"\"},{\"name\":\"店铺音乐专区\",\"jump_url\":\"\"},{\"name\":\"打游戏专区\",\"jump_url\":\"\"},{\"name\":\"K歌必唱专区\",\"jump_url\":\"\"},{\"name\":\"开车专区\",\"jump_url\":\"\"},{\"name\":\"咖啡馆专区\",\"jump_url\":\"\"},{\"name\":\"蹦迪专用专区\",\"jump_url\":\"\"},{\"name\":\"校园专区\",\"jump_url\":\"\"}]},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104103232420148.png\",\"id\":2007,\"name\":\"主题\",\"children\":[{\"name\":\"经典老歌专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F51\"},{\"name\":\"春节专区\",\"jump_url\":\"https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F73\"},{\"name\":\"成名曲专区\",\"jump_url\":\"\"},{\"name\":\"舞曲专区\",\"jump_url\":\"\"},{\"name\":\"儿歌专区\",\"jump_url\":\"\"},{\"name\":\"新歌推荐专区\",\"jump_url\":\"\"},{\"name\":\"情歌对唱专区\",\"jump_url\":\"\"},{\"name\":\"励志专区\",\"jump_url\":\"\"},{\"name\":\"军旅红歌专区\",\"jump_url\":\"\"},{\"name\":\"铃声专区\",\"jump_url\":\"\"},{\"name\":\"神曲专区\",\"jump_url\":\"\"},{\"name\":\"城市风情专区\",\"jump_url\":\"\"},{\"name\":\"会员专属专区\",\"jump_url\":\"\"},{\"name\":\"BGM专区\",\"jump_url\":\"\"}]},{\"has_child\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172345416784.png\",\"id\":32,\"name\":\"年代\",\"children\":[{\"name\":\"70后\",\"jump_url\":\"\"},{\"name\":\"80后\",\"jump_url\":\"\"},{\"name\":\"90后\",\"jump_url\":\"\"},{\"name\":\"00后\",\"jump_url\":\"\"}]},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191202/20191202161746384633.png\",\"id\":2009,\"name\":\"语言\",\"children\":[{\"name\":\"国语专区\",\"jump_url\":\"\"},{\"name\":\"粤语专区\",\"jump_url\":\"\"},{\"name\":\"英语专区\",\"jump_url\":\"\"},{\"name\":\"韩语专区\",\"jump_url\":\"\"},{\"name\":\"日语专区\",\"jump_url\":\"\"},{\"name\":\"法语专区\",\"jump_url\":\"\"},{\"name\":\"闽南语专区\",\"jump_url\":\"\"},{\"name\":\"客家语专区\",\"jump_url\":\"\"},{\"name\":\"小语种专区\",\"jump_url\":\"\"}]},{\"has_child\":1,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20191104/20191104102344527371.png\",\"id\":1599,\"name\":\"风格\",\"children\":[{\"name\":\"流行专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1601&subname=%E6%B5%81%E8%A1%8C%E4%B8%93%E5%8C%BA\"},{\"name\":\"电子专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1615&subname=%E7%94%B5%E5%AD%90%E4%B8%93%E5%8C%BA\"},{\"name\":\"摇滚专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1611&subname=%E6%91%87%E6%BB%9A%E4%B8%93%E5%8C%BA\"},{\"name\":\"纯音乐专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1613&subname=%E7%BA%AF%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\"},{\"name\":\"国风音乐专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1707&subname=%E5%9B%BD%E9%A3%8E%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\"},{\"name\":\"嘻哈专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1715&subname=%E5%98%BB%E5%93%88%E4%B8%93%E5%8C%BA\"},{\"name\":\"R&BSoul专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1743&subname=R&B/Soul%E4%B8%93%E5%8C%BA\"},{\"name\":\"民谣专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1761&subname=%E6%B0%91%E8%B0%A3%E4%B8%93%E5%8C%BA\"},{\"name\":\"DJ歌曲专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1775&subname=DJ%E6%AD%8C%E6%9B%B2%E4%B8%93%E5%8C%BA\"},{\"name\":\"古典专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1783&subname=%E5%8F%A4%E5%85%B8%E4%B8%93%E5%8C%BA\"},{\"name\":\"世界音乐专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1807&subname=%E4%B8%96%E7%95%8C%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\"},{\"name\":\"乡村专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1833&subname=%E4%B9%A1%E6%9D%91%E4%B8%93%E5%8C%BA\"},{\"name\":\"爵士专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1849&subname=%E7%88%B5%E5%A3%AB%E4%B8%93%E5%8C%BA\"},{\"name\":\"实验音乐专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1883&subname=%E5%AE%9E%E9%AA%8C%E9%9F%B3%E4%B9%90%E4%B8%93%E5%8C%BA\"},{\"name\":\"拉丁专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1895&subname=%E6%8B%89%E4%B8%81%E4%B8%93%E5%8C%BA\"},{\"name\":\"金属专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1901&subname=%E9%87%91%E5%B1%9E%E4%B8%93%E5%8C%BA\"},{\"name\":\"朋克专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1915&subname=%E6%9C%8B%E5%85%8B%E4%B8%93%E5%8C%BA\"},{\"name\":\"雷鬼专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1917&subname=%E9%9B%B7%E9%AC%BC%E4%B8%93%E5%8C%BA\"},{\"name\":\"布鲁斯专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1925&subname=%E5%B8%83%E9%B2%81%E6%96%AF%E4%B8%93%E5%8C%BA\"},{\"name\":\"ACG歌曲专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1921&subname=ACG%E6%AD%8C%E6%9B%B2%E4%B8%93%E5%8C%BA\"},{\"name\":\"中国特色专区\",\"jump_url\":\"https://h5.kugou.com/apps/style-category/dist/index.html?bid=1599&bname=%E9%A3%8E%E6%A0%BC&subid=1923&subname=%E4%B8%AD%E5%9B%BD%E7%89%B9%E8%89%B2%E4%B8%93%E5%8C%BA\"}]},{\"has_child\":0,\"icon\":\"http://imge.kugou.com/mcommon/{size}/20181130/20181130172408696210.png\",\"id\":58,\"name\":\"乐器\",\"children\":[{\"name\":\"古筝\",\"jump_url\":\"\"},{\"name\":\"钢琴\",\"jump_url\":\"\"},{\"name\":\"笛子\",\"jump_url\":\"\"},{\"name\":\"二胡\",\"jump_url\":\"\"},{\"name\":\"吉他\",\"jump_url\":\"\"},{\"name\":\"萨克斯\",\"jump_url\":\"\"},{\"name\":\"八音盒\",\"jump_url\":\"\"},{\"name\":\"小提琴\",\"jump_url\":\"\"},{\"name\":\"葫芦丝\",\"jump_url\":\"\"},{\"name\":\"唢呐\",\"jump_url\":\"\"}]}]},\"errcode\":0}"; 73 | 74 | 75 | static void checkResult(Response* resp, char* jstrOutput); 76 | 77 | void test2() 78 | { 79 | printf("=========================================\n"); 80 | printf("\t\tRunning %s\n", __FUNCTION__); 81 | printf("=========================================\n"); 82 | Response resp; 83 | memset(&resp, 0, sizeof(resp)); 84 | 85 | /* string to struct */ 86 | int ret = csonJsonStr2Struct(jStr, &resp, ResponseTbl); 87 | printf("decode ret=%d\n", ret); 88 | CHECK_NUMBER(ret, 0); 89 | 90 | /* test print */ 91 | //csonPrintProperty(&resp, ResponseTbl); 92 | 93 | char* jstrOutput; 94 | ret = csonStruct2JsonStr(&jstrOutput, &resp, ResponseTbl); 95 | CHECK_NUMBER(ret, 0); 96 | printf("encode ret=%d\nJson:%s\n", ret, jstrOutput); 97 | 98 | /*assert check*/ 99 | checkResult(&resp, jstrOutput); 100 | 101 | free(jstrOutput); 102 | csonFreePointer(&resp, ResponseTbl); 103 | 104 | printf("Successed %s.\n", __FUNCTION__); 105 | } 106 | 107 | void checkResult(Response* resp, char* jstrOutput){ 108 | 109 | CHECK_NUMBER(resp->status, 1); 110 | CHECK_NUMBER(resp->data.timestamp, 1579069151); 111 | CHECK_NUMBER(resp->data.infoNum, 9); 112 | 113 | CHECK_NUMBER(resp->data.info[0].has_child, 1); 114 | CHECK_STRING(resp->data.info[0].icon, "http://imge.kugou.com/mcommon/{size}/20181130/20181130172444711866.png"); 115 | CHECK_NUMBER(resp->data.info[0].id, 153); 116 | CHECK_STRING(resp->data.info[0].name, "专区"); 117 | CHECK_NUMBER(resp->data.info[0].childrenNum, 16); 118 | CHECK_STRING(resp->data.info[0].children[0].name, "DJ专区"); 119 | CHECK_STRING(resp->data.info[0].children[0].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F1"); 120 | CHECK_STRING(resp->data.info[0].children[1].name, "抖音专区"); 121 | CHECK_STRING(resp->data.info[0].children[1].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F45"); 122 | CHECK_STRING(resp->data.info[0].children[2].name, "儿童专区"); 123 | CHECK_STRING(resp->data.info[0].children[2].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F3"); 124 | CHECK_STRING(resp->data.info[0].children[3].name, "网络专区"); 125 | CHECK_STRING(resp->data.info[0].children[3].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F23"); 126 | CHECK_STRING(resp->data.info[0].children[4].name, "车载专区"); 127 | CHECK_STRING(resp->data.info[0].children[4].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F9"); 128 | CHECK_STRING(resp->data.info[0].children[5].name, "广场舞专区"); 129 | CHECK_STRING(resp->data.info[0].children[5].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F11"); 130 | CHECK_STRING(resp->data.info[0].children[6].name, "轻音乐专区"); 131 | CHECK_STRING(resp->data.info[0].children[6].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F17"); 132 | CHECK_STRING(resp->data.info[0].children[7].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F19"); 133 | CHECK_STRING(resp->data.info[0].children[7].name, "情歌专区"); 134 | CHECK_STRING(resp->data.info[0].children[8].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F7"); 135 | CHECK_STRING(resp->data.info[0].children[8].name, "国风专区"); 136 | CHECK_STRING(resp->data.info[0].children[9].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F27"); 137 | CHECK_STRING(resp->data.info[0].children[9].name, "电音专区"); 138 | CHECK_STRING(resp->data.info[0].children[10].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F29"); 139 | CHECK_STRING(resp->data.info[0].children[10].name, "欧美专区"); 140 | CHECK_STRING(resp->data.info[0].children[11].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F5"); 141 | CHECK_STRING(resp->data.info[0].children[11].name, "ACG专区"); 142 | CHECK_STRING(resp->data.info[0].children[12].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F15"); 143 | CHECK_STRING(resp->data.info[0].children[12].name, "影视专区"); 144 | CHECK_STRING(resp->data.info[0].children[13].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F25"); 145 | CHECK_STRING(resp->data.info[0].children[13].name, "戏曲专区"); 146 | CHECK_STRING(resp->data.info[0].children[14].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F13"); 147 | CHECK_STRING(resp->data.info[0].children[14].name, "粤剧专区"); 148 | CHECK_STRING(resp->data.info[0].children[15].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F31"); 149 | CHECK_STRING(resp->data.info[0].children[15].name, "韩流专区"); 150 | 151 | 152 | CHECK_NUMBER(resp->data.info[1].has_child, 1); 153 | CHECK_STRING(resp->data.info[1].icon, "http://imge.kugou.com/mcommon/{size}/20191104/20191104103209217784.png"); 154 | CHECK_NUMBER(resp->data.info[1].id, 2005); 155 | CHECK_STRING(resp->data.info[1].name, "心情"); 156 | CHECK_NUMBER(resp->data.info[1].childrenNum, 9); 157 | CHECK_STRING(resp->data.info[1].children[0].name, "伤感专区"); 158 | CHECK_STRING(resp->data.info[1].children[1].name, "安静专区"); 159 | CHECK_STRING(resp->data.info[1].children[2].name, "对抗抑郁专区"); 160 | CHECK_STRING(resp->data.info[1].children[3].name, "轻松专区"); 161 | CHECK_STRING(resp->data.info[1].children[4].name, "激情专区"); 162 | CHECK_STRING(resp->data.info[1].children[5].name, "甜蜜专区"); 163 | CHECK_STRING(resp->data.info[1].children[6].name, "开心专区"); 164 | CHECK_STRING(resp->data.info[1].children[7].name, "想念专区"); 165 | CHECK_STRING(resp->data.info[1].children[8].name, "疗伤专区"); 166 | 167 | 168 | CHECK_NUMBER(resp->data.info[2].has_child, 1); 169 | CHECK_STRING(resp->data.info[2].icon, "http://imge.kugou.com/mcommon/{size}/20181130/20181130172455112096.png"); 170 | CHECK_NUMBER(resp->data.info[2].id, 1263); 171 | CHECK_STRING(resp->data.info[2].name, "特色"); 172 | CHECK_NUMBER(resp->data.info[2].childrenNum, 16); 173 | CHECK_STRING(resp->data.info[2].children[0].name, "官方歌单"); 174 | CHECK_STRING(resp->data.info[2].children[1].name, "重返2010专区"); 175 | CHECK_STRING(resp->data.info[2].children[2].name, "佛乐专区"); 176 | CHECK_STRING(resp->data.info[2].children[3].name, "综艺专区"); 177 | CHECK_STRING(resp->data.info[2].children[4].name, "首发专区"); 178 | CHECK_STRING(resp->data.info[2].children[5].name, "音乐人专区"); 179 | CHECK_STRING(resp->data.info[2].children[6].name, "古典乐专区"); 180 | CHECK_STRING(resp->data.info[2].children[7].name, "HiFi专区"); 181 | CHECK_STRING(resp->data.info[2].children[8].name, "英语学习专区"); 182 | CHECK_STRING(resp->data.info[2].children[9].name, "2019年终专区"); 183 | CHECK_STRING(resp->data.info[2].children[10].name, "有声电台"); 184 | CHECK_STRING(resp->data.info[2].children[11].name, "Urban专区"); 185 | CHECK_STRING(resp->data.info[2].children[12].name, "入驻厂牌专区"); 186 | CHECK_STRING(resp->data.info[2].children[13].name, "游戏专区"); 187 | CHECK_STRING(resp->data.info[2].children[14].name, "说唱专区"); 188 | CHECK_STRING(resp->data.info[2].children[15].name, "冬天听什么专区"); 189 | CHECK_STRING(resp->data.info[2].children[1].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F65"); 190 | CHECK_STRING(resp->data.info[2].children[3].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2findex.html%23%2fmobile%2fhome%2f37"); 191 | CHECK_STRING(resp->data.info[2].children[4].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F35"); 192 | CHECK_STRING(resp->data.info[2].children[5].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F33"); 193 | CHECK_STRING(resp->data.info[2].children[7].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F21"); 194 | CHECK_STRING(resp->data.info[2].children[9].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F69"); 195 | CHECK_STRING(resp->data.info[2].children[10].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F39"); 196 | CHECK_STRING(resp->data.info[2].children[13].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F71"); 197 | CHECK_STRING(resp->data.info[2].children[14].jump_url, "https://miniapp.kugou.com/node/v2?type=1&id=74&path=%2Findex.html%23%2Fmobile%2Fhome%2F63"); 198 | 199 | 200 | CHECK_NUMBER(resp->data.info[3].has_child, 1); 201 | CHECK_STRING(resp->data.info[3].icon, "http://imge.kugou.com/mcommon/{size}/20191104/20191104103220446249.png"); 202 | CHECK_NUMBER(resp->data.info[3].id, 2003); 203 | CHECK_STRING(resp->data.info[3].name, "场景"); 204 | CHECK_NUMBER(resp->data.info[3].childrenNum, 9); 205 | 206 | CHECK_NUMBER(resp->data.info[4].has_child, 1); 207 | CHECK_STRING(resp->data.info[4].icon, "http://imge.kugou.com/mcommon/{size}/20191104/20191104103232420148.png"); 208 | CHECK_NUMBER(resp->data.info[4].id, 2007); 209 | CHECK_STRING(resp->data.info[4].name, "主题"); 210 | CHECK_NUMBER(resp->data.info[4].childrenNum, 14); 211 | 212 | CHECK_NUMBER(resp->data.info[5].has_child, 0); 213 | CHECK_STRING(resp->data.info[5].icon, "http://imge.kugou.com/mcommon/{size}/20181130/20181130172345416784.png"); 214 | CHECK_NUMBER(resp->data.info[5].id, 32); 215 | CHECK_STRING(resp->data.info[5].name, "年代"); 216 | CHECK_NUMBER(resp->data.info[5].childrenNum, 4); 217 | 218 | CHECK_NUMBER(resp->data.info[6].has_child, 1); 219 | CHECK_STRING(resp->data.info[6].icon, "http://imge.kugou.com/mcommon/{size}/20191202/20191202161746384633.png"); 220 | CHECK_NUMBER(resp->data.info[6].id, 2009); 221 | CHECK_STRING(resp->data.info[6].name, "语言"); 222 | CHECK_NUMBER(resp->data.info[6].childrenNum, 9); 223 | 224 | CHECK_NUMBER(resp->data.info[7].has_child, 1); 225 | CHECK_STRING(resp->data.info[7].icon, "http://imge.kugou.com/mcommon/{size}/20191104/20191104102344527371.png"); 226 | CHECK_NUMBER(resp->data.info[7].id, 1599); 227 | CHECK_STRING(resp->data.info[7].name, "风格"); 228 | CHECK_NUMBER(resp->data.info[7].childrenNum, 21); 229 | 230 | CHECK_NUMBER(resp->data.info[8].has_child, 0); 231 | CHECK_STRING(resp->data.info[8].icon, "http://imge.kugou.com/mcommon/{size}/20181130/20181130172408696210.png"); 232 | CHECK_NUMBER(resp->data.info[8].id, 58); 233 | CHECK_STRING(resp->data.info[8].name, "乐器"); 234 | CHECK_NUMBER(resp->data.info[8].childrenNum, 10); 235 | 236 | CHECK_STRING(jstrOutput, encodeTest); 237 | } -------------------------------------------------------------------------------- /inc/cson.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cson.h 3 | * @author sun_chb@126.com 4 | */ 5 | #ifndef _CSON_H_ 6 | #define _CSON_H_ 7 | 8 | #include "stddef.h" 9 | 10 | /** 11 | * @brief error code of parser. 12 | */ 13 | #define ERR_NONE (0) /**< success */ 14 | #define ERR_MEMORY (-1) /**< malloc failed */ 15 | #define ERR_TYPE (-2) /**< type matching error */ 16 | #define ERR_MISSING_FIELD (-3) /**< field not found */ 17 | #define ERR_FORMAT (-4) /**< input json string format error */ 18 | #define ERR_ARGS (-5) /**< args error */ 19 | #define ERR_OVERFLOW (-6) /**< value overflow */ 20 | 21 | /** 22 | * @brief the type of json object. 23 | */ 24 | typedef enum { 25 | CSON_OBJECT, 26 | CSON_ARRAY, 27 | CSON_STRING, 28 | CSON_INTEGER, 29 | CSON_REAL, 30 | CSON_TRUE, 31 | CSON_FALSE, 32 | CSON_NULL 33 | } cson_type; 34 | 35 | typedef void* cson_t; 36 | 37 | /** 38 | * @brief define the function type of json parse/pack function group 39 | */ 40 | typedef cson_t (*func_cson_object_get)(const cson_t object, const char* key); 41 | typedef cson_type (*func_cson_typeof)(cson_t object); 42 | typedef cson_t (*func_cson_loadb)(const char *buffer, size_t buflen); 43 | typedef void (*func_cson_decref)(cson_t object); 44 | typedef const char* (*func_cson_string_value)(const cson_t object); 45 | typedef size_t (*func_cson_string_length)(const cson_t object); 46 | typedef long long (*func_cson_integer_value)(const cson_t object); 47 | typedef double (*func_cson_real_value)(const cson_t object); 48 | typedef char (*func_cson_bool_value)(const cson_t object); 49 | typedef size_t (*func_cson_array_size)(const cson_t object); 50 | typedef cson_t (*func_cson_array_get)(const cson_t object, size_t index); 51 | typedef cson_t (*func_cson_new)(); 52 | typedef char* (*func_cson_to_string)(cson_t object); 53 | typedef cson_t (*func_cson_integer)(long long val); 54 | typedef cson_t (*func_cson_string)(const char* val); 55 | typedef cson_t (*func_cson_bool)(char val); 56 | typedef cson_t (*func_cson_real)(double val); 57 | typedef cson_t (*func_cson_array)(); 58 | typedef int (*func_cson_array_add)(cson_t array, cson_t obj); 59 | typedef int (*func_cson_object_set_new)(cson_t rootObj, const char* field, cson_t obj); 60 | 61 | /** 62 | * @brief define the cson interface 63 | */ 64 | typedef struct { 65 | func_cson_object_get cson_object_get; 66 | func_cson_typeof cson_typeof; 67 | func_cson_loadb cson_loadb; 68 | func_cson_decref cson_decref; 69 | func_cson_string_value cson_string_value; 70 | func_cson_string_length cson_string_length; 71 | func_cson_integer_value cson_integer_value; 72 | func_cson_real_value cson_real_value; 73 | func_cson_bool_value cson_bool_value; 74 | func_cson_array_size cson_array_size; 75 | func_cson_array_get cson_array_get; 76 | func_cson_new cson_object; 77 | func_cson_to_string cson_to_string; 78 | func_cson_integer cson_integer; 79 | func_cson_string cson_string; 80 | func_cson_bool cson_bool; 81 | func_cson_real cson_real; 82 | func_cson_array cson_array; 83 | func_cson_array_add cson_array_add; 84 | func_cson_object_set_new cson_object_set_new; 85 | } cson_interface; 86 | 87 | /** 88 | * @brief the description of property in struct. 89 | * 90 | * @TODO: Try to simplify the struct 91 | */ 92 | typedef struct reflect_item_t { 93 | const char* field; /**< field */ 94 | size_t offset; /**< offset of property */ 95 | size_t size; /**< size of property */ 96 | cson_type type; /**< corresponding json type */ 97 | const struct reflect_item_t* reflect_tbl; /**< must be specified when type is object or array */ 98 | size_t arrayItemSize; /**< size of per array item. must be specified when type is array */ 99 | const char* arrayCountField; /**< field saving array size */ 100 | int exArgs; /**< paser return failure when the field is not found and nullable equals to 0 */ 101 | } reflect_item_t; 102 | 103 | extern const reflect_item_t integerReflectTbl[]; 104 | extern const reflect_item_t stringReflectTbl[]; 105 | extern const reflect_item_t boolReflectTbl[]; 106 | extern const reflect_item_t realReflectTbl[]; 107 | 108 | #define _ex_args_nullable (0x01) 109 | #define _ex_args_exclude_decode (0x02) 110 | #define _ex_args_exclude_encode (0x04) 111 | #define _ex_args_all (_ex_args_nullable | _ex_args_exclude_decode | _ex_args_exclude_encode) 112 | 113 | #define _offset(type, field) (size_t)(&(((type*)0)->field)) 114 | #define _size(type, field) (sizeof(((type*)0)->field)) 115 | #define _property(type, field, jtype, tbl, nullable) {#field, _offset(type, field), _size(type, field), jtype, tbl, 0, NULL, nullable} 116 | #define _property_end() {NULL, 0, 0, CSON_NULL, NULL, 0, NULL, 1} 117 | 118 | /** 119 | * @brief Declaring integer properties. 120 | * 121 | * @param type: type of struct 122 | * @param field: field name of properties 123 | * 124 | */ 125 | #define _property_int(type, field) _property(type, field, CSON_INTEGER, integerReflectTbl, _ex_args_nullable) 126 | 127 | /** 128 | * @brief Declaring real properties. 129 | * 130 | * @param type: type of struct 131 | * @param field: field name of properties 132 | * 133 | */ 134 | #define _property_real(type, field) _property(type, field, CSON_REAL, realReflectTbl, _ex_args_nullable) 135 | 136 | /** 137 | * @brief Declaring bool properties. 138 | * 139 | * @param type: type of struct 140 | * @param field: field name of properties 141 | * 142 | */ 143 | #define _property_bool(type, field) _property(type, field, CSON_TRUE, boolReflectTbl, _ex_args_nullable) 144 | 145 | /** 146 | * @brief Declaring string properties. 147 | * 148 | * @param type: type of struct 149 | * @param field: field name of properties 150 | * 151 | */ 152 | #define _property_string(type, field) _property(type, field, CSON_STRING, stringReflectTbl, _ex_args_nullable) 153 | 154 | /** 155 | * @brief Declaring struct properties. 156 | * 157 | * @param type: type of struct 158 | * @param field: field name of properties 159 | * @param tbl: property description table of sub-struct 160 | * 161 | */ 162 | #define _property_obj(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, _ex_args_nullable) 163 | 164 | /** 165 | * @brief Declaring array properties. 166 | * 167 | * @param type: type of struct 168 | * @param field: field name of properties 169 | * @param tbl: property description table of type of array 170 | * @param subType: type of array 171 | * @param count: property to save the array size 172 | * 173 | */ 174 | #define _property_array(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, _ex_args_nullable} 175 | #define _property_array_object(type, field, tbl, subType, count) _property_array(type, field, tbl, subType, count) 176 | #define _property_array_int(type, field, subType, count) _property_array(type, field, integerReflectTbl, subType, count) 177 | #define _property_array_string(type, field, subType, count) _property_array(type, field, stringReflectTbl, subType, count) 178 | #define _property_array_real(type, field, subType, count) _property_array(type, field, realReflectTbl, subType, count) 179 | #define _property_array_bool(type, field, subType, count) _property_array(type, field, boolReflectTbl, subType, count) 180 | 181 | /** 182 | * @brief nonull definitions. parser will stop and return error code when field not found which declared whit it. 183 | * 184 | * @param refer to comment of nullable definition 185 | */ 186 | #define _property_int_nonull(type, field) _property(type, field, CSON_INTEGER, NULL, 0) 187 | #define _property_real_nonull(type, field) _property(type, field, CSON_REAL, NULL, 0) 188 | #define _property_bool_nonull(type, field) _property(type, field, CSON_TRUE, NULL, 0) 189 | #define _property_string_nonull(type, field) _property(type, field, CSON_STRING, NULL, 0) 190 | #define _property_obj_nonull(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, 0) 191 | #define _property_array_nonull(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, 0} 192 | #define _property_array_object_nonull(type, field, tbl, subType, count) _property_array_nonull(type, field, tbl, subType, count) 193 | #define _property_array_int_nonull(type, field, subType, count) _property_array_nonull(type, field, integerReflectTbl, subType, count) 194 | #define _property_array_string_nonull(type, field, subType, count) _property_array_nonull(type, field, stringReflectTbl, subType, count) 195 | #define _property_array_real_nonull(type, field, subType, count) _property_array_nonull(type, field, realReflectTbl, subType, count) 196 | #define _property_array_bool_nonull(type, field, subType, count) _property_array_nonull(type, field, boolReflectTbl, subType, count) 197 | 198 | /** 199 | * @brief nonull definitions. parser will stop and return error code when field not found which declared whit it. 200 | * 201 | * @param refer to comment of nullable definition 202 | * @param args opptional with _ex_args_nullable(0x01) _ex_args_exclude_decode(0x02) _ex_args_exclude_encode(0x04) 203 | */ 204 | #define _property_int_ex(type, field, args) _property(type, field, CSON_INTEGER, NULL, args) 205 | #define _property_real_ex(type, field, args) _property(type, field, CSON_REAL, NULL, args) 206 | #define _property_bool_ex(type, field, args) _property(type, field, CSON_TRUE, NULL, args) 207 | #define _property_string_ex(type, field, args) _property(type, field, CSON_STRING, NULL, args) 208 | #define _property_obj_ex(type, field, tbl, args) _property(type, field, CSON_OBJECT, tbl, args) 209 | #define _property_array_ex(type, field, tbl, subType, count, args) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, args} 210 | #define _property_array_object_ex(type, field, tbl, subType, count, args) _property_array_ex(type, field, tbl, subType, count) 211 | #define _property_array_int_ex(type, field, subType, count, args) _property_array_ex(type, field, integerReflectTbl, subType, count) 212 | #define _property_array_string_ex(type, field, subType, count, args) _property_array_ex(type, field, stringReflectTbl, subType, count) 213 | #define _property_array_real_ex(type, field, subType, count, args) _property_array_ex(type, field, realReflectTbl, subType, count) 214 | #define _property_array_bool_ex(type, field, subType, count, args) _property_array_ex(type, field, boolReflectTbl, subType, count) 215 | 216 | /** 217 | * @brief function type of csonLoopProperty. 218 | * 219 | * @param obj: pointer of property. 220 | * @param tbl: property of field. 221 | * 222 | * @return void*(reserved). 223 | */ 224 | typedef void* (*loop_func_t)(void* pData, const reflect_item_t* tbl); 225 | 226 | /** 227 | * @brief loop all property and process property by @func 228 | * 229 | * @param obj: object to be operated. 230 | * @param tbl: property of field. 231 | * @param func: callback 232 | * 233 | * @return void. 234 | */ 235 | void csonLoopProperty(void* obj, const reflect_item_t* tbl, loop_func_t func); 236 | 237 | /** 238 | * @brief convert json string to struct object. 239 | * 240 | * @param jstr: json string 241 | * @param output: target object 242 | * @param tbl: property table of output. 243 | * 244 | * @return ERR_NONE on success, otherwise failed. 245 | */ 246 | int csonJsonStr2Struct(const char* jstr, void* output, const reflect_item_t* tbl); 247 | 248 | /** 249 | * @brief convert struct object to json string. 250 | * 251 | * @param jstr: output json string 252 | * @param output: input struct object 253 | * @param tbl: property table of input. 254 | * 255 | * @return ERR_NONE on success, otherwise failed. 256 | */ 257 | int csonStruct2JsonStr(char** jstr, void* input, const reflect_item_t* tbl); 258 | 259 | /** 260 | * @brief Iterative output properties of data 261 | * 262 | * @param pData: struct object 263 | * @param tbl: property table of input. 264 | * 265 | * @return void. 266 | */ 267 | void csonPrintProperty(void* pData, const reflect_item_t* tbl); 268 | 269 | /** 270 | * @brief Iterative free pointer of data 271 | * 272 | * @param pData: struct object 273 | * @param tbl: property table of input. 274 | * 275 | * @return void. 276 | */ 277 | void csonFreePointer(void* list, const reflect_item_t* tbl); 278 | 279 | #endif -------------------------------------------------------------------------------- /src/cson.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cson.c 3 | * @author sun_chb@126.com 4 | */ 5 | #include "cson.h" 6 | #include "stdio.h" 7 | #include "stdlib.h" 8 | #include "stddef.h" 9 | #include "limits.h" 10 | #include "string.h" 11 | 12 | extern cson_interface csomImpl; 13 | 14 | #define cson_object_get csomImpl.cson_object_get 15 | #define cson_typeof csomImpl.cson_typeof 16 | #define cson_loadb csomImpl.cson_loadb 17 | #define cson_decref csomImpl.cson_decref 18 | #define cson_string_value csomImpl.cson_string_value 19 | #define cson_string_length csomImpl.cson_string_length 20 | #define cson_integer_value csomImpl.cson_integer_value 21 | #define cson_real_value csomImpl.cson_real_value 22 | #define cson_bool_value csomImpl.cson_bool_value 23 | #define cson_array_size csomImpl.cson_array_size 24 | #define cson_array_get csomImpl.cson_array_get 25 | #define cson_object csomImpl.cson_object 26 | #define cson_to_string csomImpl.cson_to_string 27 | #define cson_integer csomImpl.cson_integer 28 | #define cson_string csomImpl.cson_string 29 | #define cson_bool csomImpl.cson_bool 30 | #define cson_real csomImpl.cson_real 31 | #define cson_array csomImpl.cson_array 32 | #define cson_array_add csomImpl.cson_array_add 33 | #define cson_object_set_new csomImpl.cson_object_set_new 34 | #define cson_is_number(type) (type == CSON_REAL || type == CSON_INTEGER) 35 | #define cson_is_bool(type) (type == CSON_TRUE || type == CSON_FALSE) 36 | 37 | const reflect_item_t integerReflectTbl[] = { 38 | {"0Integer", 0, sizeof(int), CSON_INTEGER, NULL, 0, NULL, 1}, 39 | {} 40 | }; 41 | 42 | const reflect_item_t stringReflectTbl[] = { 43 | {"0String", 0, sizeof(char*), CSON_STRING, NULL, 0, NULL, 1}, 44 | {} 45 | }; 46 | 47 | const reflect_item_t realReflectTbl[] = { 48 | {"0Real", 0, sizeof(double), CSON_REAL, NULL, 0, NULL, 1}, 49 | {} 50 | }; 51 | 52 | const reflect_item_t boolReflectTbl[] = { 53 | {"0Bool", 0, sizeof(int), CSON_TRUE, NULL, 0, NULL, 1}, 54 | {} 55 | }; 56 | 57 | /* 58 | * reflecter functions 59 | */ 60 | static const reflect_item_t* getReflexItem(const char* field, const reflect_item_t* tbl, int* pIndex); 61 | static void* csonGetProperty(void* obj, const char* field, const reflect_item_t* tbl, int* pIndex); 62 | static void csonSetProperty(void* obj, const char* field, void* data, const reflect_item_t* tbl); 63 | static void csonSetPropertyFast(void* obj, const void* data, const reflect_item_t* tbl); 64 | 65 | /* 66 | * integer util functions 67 | */ 68 | typedef union { 69 | char c; 70 | short s; 71 | int i; 72 | long long l; 73 | } integer_val_t; 74 | 75 | static long long getIntegerValueFromPointer(void* ptr, int size); 76 | static int getIntegerValue(cson_t jo_tmp, int size, integer_val_t* i); 77 | static int convertInteger(long long val, int size, integer_val_t* i); 78 | static int checkInteger(long long val, int size); 79 | 80 | /* 81 | * packer functions 82 | */ 83 | typedef int (*json_pack_proc)(void* input, const reflect_item_t* tbl, int index, cson_t* obj); 84 | 85 | static int getJsonObject(void* input, const reflect_item_t* tbl, int index, cson_t* obj); 86 | static int getJsonArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj); 87 | static int getJsonString(void* input, const reflect_item_t* tbl, int index, cson_t* obj); 88 | static int getJsonInteger(void* input, const reflect_item_t* tbl, int index, cson_t* obj); 89 | static int getJsonReal(void* input, const reflect_item_t* tbl, int index, cson_t* obj); 90 | static int getJsonBool(void* input, const reflect_item_t* tbl, int index, cson_t* obj); 91 | 92 | json_pack_proc jsonPackTbl[] = { 93 | getJsonObject, 94 | getJsonArray, 95 | getJsonString, 96 | getJsonInteger, 97 | getJsonReal, 98 | getJsonBool, 99 | getJsonBool, 100 | NULL 101 | }; 102 | 103 | static int csonStruct2JsonObj(cson_t obj, void* input, const reflect_item_t* tbl); 104 | 105 | /* 106 | * parser functions 107 | */ 108 | typedef int (*json_obj_proc)(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 109 | 110 | static int parseJsonObject(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 111 | static int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 112 | static int parseJsonString(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 113 | static int parseJsonInteger(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 114 | static int parseJsonReal(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 115 | static int parseJsonBool(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 116 | 117 | json_obj_proc jsonObjProcTbl[] = { 118 | parseJsonObject, 119 | parseJsonArray, 120 | parseJsonString, 121 | parseJsonInteger, 122 | parseJsonReal, 123 | parseJsonBool, 124 | parseJsonBool, 125 | NULL 126 | }; 127 | 128 | static int parseJsonObjectDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 129 | static int parseJsonArrayDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 130 | static int parseJsonStringDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 131 | static int parseJsonIntegerDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 132 | static int parseJsonRealDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index); 133 | 134 | json_obj_proc jsonObjDefaultTbl[] = { 135 | parseJsonObjectDefault, 136 | parseJsonArrayDefault, 137 | parseJsonStringDefault, 138 | parseJsonIntegerDefault, 139 | parseJsonRealDefault, 140 | parseJsonIntegerDefault, 141 | parseJsonIntegerDefault, 142 | NULL 143 | }; 144 | 145 | static int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl); 146 | 147 | int csonStruct2JsonStr(char** jstr, void* input, const reflect_item_t* tbl) 148 | { 149 | cson_t jsonPack = cson_object(); 150 | 151 | if (!jsonPack) return ERR_MEMORY; 152 | 153 | int ret = csonStruct2JsonObj(jsonPack, input, tbl); 154 | 155 | if (ret == ERR_NONE) { 156 | char* dumpStr = cson_to_string(jsonPack); 157 | if (dumpStr == NULL) { 158 | ret = ERR_MEMORY; 159 | } else { 160 | *jstr = dumpStr; 161 | } 162 | } 163 | 164 | cson_decref(jsonPack); 165 | return ret; 166 | } 167 | 168 | int csonStruct2JsonObj(cson_t obj, void* input, const reflect_item_t* tbl) 169 | { 170 | int i = 0; 171 | int ret = ERR_NONE; 172 | 173 | if (!obj || !input || !tbl) return ERR_ARGS; 174 | 175 | while (1) { 176 | if (tbl[i].field == NULL) break; 177 | 178 | if(tbl[i].exArgs & _ex_args_exclude_encode){ 179 | i++; 180 | continue; 181 | } 182 | 183 | cson_t joTmp = NULL; 184 | int jsonType = tbl[i].type; 185 | 186 | if (jsonPackTbl[jsonType] != NULL) { 187 | ret = jsonPackTbl[jsonType](input, tbl, i, &joTmp); 188 | } 189 | 190 | if (ret != ERR_NONE ) { 191 | printf("!!!!pack error on field:%s, cod=%d!!!!\n", tbl[i].field, ret); 192 | if (!(tbl[i].exArgs & _ex_args_nullable)) return ret; 193 | } else { 194 | cson_object_set_new(obj, tbl[i].field, joTmp); 195 | } 196 | 197 | i++; 198 | } 199 | 200 | return ERR_NONE; 201 | } 202 | 203 | int getJsonInteger(void* input, const reflect_item_t* tbl, int index, cson_t* obj) 204 | { 205 | if (tbl[index].size != sizeof(char) && 206 | tbl[index].size != sizeof(short) && 207 | tbl[index].size != sizeof(int) && 208 | tbl[index].size != sizeof(long long)) { 209 | printf("Unsupported size(=%ld) of integer.\n", tbl[index].size); 210 | printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field); 211 | return ERR_OVERFLOW; 212 | } 213 | 214 | void* pSrc = (void*)((char*)input + tbl[index].offset); 215 | 216 | long long val = getIntegerValueFromPointer(pSrc, tbl[index].size); 217 | 218 | *obj = cson_integer(val); 219 | 220 | return ERR_NONE; 221 | } 222 | 223 | int getJsonString(void* input, const reflect_item_t* tbl, int index, cson_t* obj) 224 | { 225 | void* pSrc = (void*)((char*)input + tbl[index].offset); 226 | 227 | if (*((char**)pSrc) == NULL) return ERR_MISSING_FIELD; 228 | 229 | *obj = cson_string(*((char**)pSrc)); 230 | return ERR_NONE; 231 | } 232 | 233 | int getJsonObject(void* input, const reflect_item_t* tbl, int index, cson_t* obj) 234 | { 235 | void* pSrc = (void*)((char*)input + tbl[index].offset); 236 | cson_t jotmp = cson_object(); 237 | int ret = csonStruct2JsonObj(jotmp, pSrc, tbl[index].reflect_tbl); 238 | 239 | if (ret == ERR_NONE) { 240 | *obj = jotmp; 241 | } else { 242 | cson_decref(jotmp); 243 | } 244 | 245 | return ret; 246 | } 247 | 248 | int getJsonArray(void* input, const reflect_item_t* tbl, int index, cson_t* obj) 249 | { 250 | int ret = ERR_NONE; 251 | int countIndex = -1; 252 | char* pSrc = (*(char**)((char*)input + tbl[index].offset)); 253 | 254 | if (pSrc == NULL) return ERR_MISSING_FIELD; 255 | 256 | void* ptr = csonGetProperty(input, tbl[index].arrayCountField, tbl, &countIndex); 257 | 258 | if (ptr == NULL || countIndex == -1) { 259 | return ERR_MISSING_FIELD; 260 | } 261 | long long size = getIntegerValueFromPointer(ptr, tbl[countIndex].size); 262 | 263 | cson_t joArray = cson_array(); 264 | 265 | long long successCount = 0; 266 | 267 | for (long long i = 0; i < size; i++) { 268 | cson_t jotmp; 269 | 270 | if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */ 271 | ret = jsonPackTbl[tbl[index].reflect_tbl[0].type](pSrc + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0, &jotmp); 272 | } else { 273 | jotmp = cson_object(); 274 | ret = csonStruct2JsonObj(jotmp, pSrc + (i * tbl[index].arrayItemSize), tbl[index].reflect_tbl); 275 | } 276 | 277 | if (ret == ERR_NONE) { 278 | successCount++; 279 | cson_array_add(joArray, jotmp); 280 | } else { 281 | printf("create array item faild.\n"); 282 | cson_decref(jotmp); 283 | } 284 | } 285 | 286 | if (successCount == 0) { 287 | cson_decref(joArray); 288 | return ERR_MISSING_FIELD; 289 | } else { 290 | *obj = joArray; 291 | return ERR_NONE; 292 | } 293 | 294 | return ret; 295 | } 296 | 297 | int getJsonReal(void* input, const reflect_item_t* tbl, int index, cson_t* obj) 298 | { 299 | if (tbl[index].size != sizeof(double)) { 300 | printf("Unsupported size(=%ld) of real.\n", tbl[index].size); 301 | printf("Please check if the type of field %s is double!\n", tbl[index].field); 302 | return ERR_OVERFLOW; 303 | } 304 | 305 | void* pSrc = (void*)((char*)input + tbl[index].offset); 306 | *obj = cson_real(*((double*)pSrc)); 307 | return ERR_NONE; 308 | } 309 | 310 | int getJsonBool(void* input, const reflect_item_t* tbl, int index, cson_t* obj) 311 | { 312 | if (tbl[index].size != sizeof(char) && 313 | tbl[index].size != sizeof(short) && 314 | tbl[index].size != sizeof(int) && 315 | tbl[index].size != sizeof(long long)) { 316 | printf("Unsupported size(=%ld) of bool.\n", tbl[index].size); 317 | printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field); 318 | return ERR_OVERFLOW; 319 | } 320 | 321 | void* pSrc = (void*)((char*)input + tbl[index].offset); 322 | 323 | if (tbl[index].size == sizeof(char)) { 324 | *obj = cson_bool(*((char*)pSrc)); 325 | } else if (tbl[index].size == sizeof(short)) { 326 | *obj = cson_bool(*((short*)pSrc)); 327 | } else if (tbl[index].size == sizeof(int)) { 328 | *obj = cson_bool(*((int*)pSrc)); 329 | } else { 330 | *obj = cson_bool(*((long long*)pSrc)); 331 | } 332 | 333 | return ERR_NONE; 334 | } 335 | 336 | 337 | int csonJsonStr2Struct(const char* jstr, void* output, const reflect_item_t* tbl) 338 | { 339 | /* load json string */ 340 | cson_t jo = cson_loadb(jstr, strlen(jstr)); 341 | 342 | if (!jo) return ERR_FORMAT; 343 | 344 | int ret = csonJsonObj2Struct(jo, output, tbl); 345 | cson_decref(jo); 346 | 347 | return ret; 348 | } 349 | 350 | int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl) 351 | { 352 | if (!jo || !output || !tbl) return ERR_ARGS; 353 | 354 | for (int i = 0;; i++) { 355 | int ret = ERR_NONE; 356 | if (tbl[i].field == NULL) break; 357 | 358 | if(tbl[i].exArgs & _ex_args_exclude_decode){ 359 | continue; 360 | } 361 | 362 | cson_t jo_tmp = cson_object_get(jo, tbl[i].field); 363 | 364 | if (jo_tmp == NULL) { 365 | ret = ERR_MISSING_FIELD; 366 | } else { 367 | 368 | int jsonType = cson_typeof(jo_tmp); 369 | 370 | if (jsonType == tbl[i].type || 371 | (cson_is_number(cson_typeof(jo_tmp)) && cson_is_number(tbl[i].type)) || 372 | (cson_is_bool(cson_typeof(jo_tmp)) && cson_is_bool(tbl[i].type))) { 373 | if (jsonObjProcTbl[tbl[i].type] != NULL) { 374 | ret = jsonObjProcTbl[tbl[i].type](jo_tmp, output, tbl, i); 375 | } 376 | } else { 377 | ret = ERR_TYPE; 378 | } 379 | } 380 | 381 | if (ret != ERR_NONE ) { 382 | printf("!!!!parse error on field:%s, cod=%d!!!!\n", tbl[i].field, ret); 383 | jsonObjDefaultTbl[tbl[i].type](NULL, output, tbl, i); 384 | if (!(tbl[i].exArgs & _ex_args_nullable)) return ret; 385 | } 386 | } 387 | 388 | return ERR_NONE; 389 | } 390 | 391 | int parseJsonString(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 392 | { 393 | const char* tempstr = cson_string_value(jo_tmp); 394 | if (NULL != tempstr) { 395 | char* pDst = (char*)malloc(strlen(tempstr) + 1); 396 | if (pDst == NULL) { 397 | return ERR_MEMORY; 398 | } 399 | strcpy(pDst, tempstr); 400 | csonSetPropertyFast(output, &pDst, tbl + index); 401 | 402 | return ERR_NONE; 403 | } 404 | 405 | return ERR_MISSING_FIELD; 406 | } 407 | 408 | int parseJsonInteger(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 409 | { 410 | int ret; 411 | integer_val_t value; 412 | ret = getIntegerValue(jo_tmp, tbl[index].size, &value); 413 | 414 | if (ret != ERR_NONE) { 415 | printf("Get integer failed!field:%s,errno:%d.\n", tbl[index].field, ret); 416 | } else { 417 | csonSetPropertyFast(output, &value, tbl + index); 418 | } 419 | 420 | return ret; 421 | } 422 | 423 | int parseJsonObject(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 424 | { 425 | return csonJsonObj2Struct(jo_tmp, (char*)output + tbl[index].offset, tbl[index].reflect_tbl); 426 | } 427 | 428 | int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 429 | { 430 | size_t arraySize = cson_array_size(jo_tmp); 431 | 432 | if (arraySize == 0) { 433 | csonSetProperty(output, tbl[index].arrayCountField, &arraySize, tbl); 434 | return ERR_NONE; 435 | } 436 | 437 | int countIndex = -1; 438 | csonGetProperty(output, tbl[index].arrayCountField, tbl, &countIndex); 439 | 440 | if (countIndex == -1) { 441 | return ERR_MISSING_FIELD; 442 | } 443 | 444 | char* pMem = (char*)malloc(arraySize * tbl[index].arrayItemSize); 445 | if (pMem == NULL) return ERR_MEMORY; 446 | 447 | memset(pMem, 0, arraySize * tbl[index].arrayItemSize); 448 | 449 | long long successCount = 0; 450 | for (size_t j = 0; j < arraySize; j++) { 451 | cson_t item = cson_array_get(jo_tmp, j); 452 | if (item != NULL) { 453 | int ret; 454 | 455 | if (tbl[index].reflect_tbl[0].field[0] == '0') { /* field start with '0' mean basic types. */ 456 | ret = jsonObjProcTbl[tbl[index].reflect_tbl[0].type](item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl, 0); 457 | } else { 458 | ret = csonJsonObj2Struct(item, pMem + (successCount * tbl[index].arrayItemSize), tbl[index].reflect_tbl); 459 | } 460 | 461 | if (ret == ERR_NONE) { 462 | successCount++; 463 | } 464 | } 465 | } 466 | 467 | integer_val_t val; 468 | if (convertInteger(successCount, tbl[countIndex].size, &val) != ERR_NONE) { 469 | successCount = 0; 470 | } 471 | 472 | if (successCount == 0) { 473 | csonSetPropertyFast(output, &successCount, tbl + countIndex); 474 | free(pMem); 475 | pMem = NULL; 476 | csonSetPropertyFast(output, &pMem, tbl + index); 477 | return ERR_MISSING_FIELD; 478 | } else { 479 | csonSetPropertyFast(output, &val, tbl + countIndex); 480 | csonSetPropertyFast(output, &pMem, tbl + index); 481 | return ERR_NONE; 482 | } 483 | } 484 | 485 | int parseJsonReal(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 486 | { 487 | if (tbl[index].size != sizeof(double)) { 488 | printf("Unsupported size(=%ld) of real.\n", tbl[index].size); 489 | printf("Please check if the type of field %s is double!\n", tbl[index].field); 490 | return ERR_OVERFLOW; 491 | } 492 | 493 | double temp; 494 | if (cson_typeof(jo_tmp) == CSON_REAL) { 495 | temp = cson_real_value(jo_tmp); 496 | } else { 497 | temp = cson_integer_value(jo_tmp); 498 | } 499 | 500 | csonSetPropertyFast(output, &temp, tbl + index); 501 | return ERR_NONE; 502 | } 503 | 504 | int parseJsonBool(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 505 | { 506 | int ret; 507 | integer_val_t value; 508 | ret = getIntegerValue(jo_tmp, tbl[index].size, &value); 509 | if (ret != ERR_NONE) { 510 | printf("Get integer failed!field:%s,errno:%d.\n", tbl[index].field, ret); 511 | } else { 512 | csonSetPropertyFast(output, &value, tbl + index); 513 | } 514 | return ret; 515 | } 516 | 517 | int parseJsonObjectDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 518 | { 519 | int i = 0; 520 | while (1) { 521 | if (tbl[i].reflect_tbl[i].field == NULL) break; 522 | 523 | if(tbl[i].exArgs & _ex_args_exclude_decode){ 524 | i++; 525 | continue; 526 | } 527 | 528 | jsonObjDefaultTbl[tbl[index].reflect_tbl[i].type](NULL, output, tbl[index].reflect_tbl, i); 529 | i++; 530 | }; 531 | return ERR_NONE; 532 | } 533 | 534 | int parseJsonArrayDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 535 | { 536 | void* temp = NULL; 537 | csonSetPropertyFast(output, &temp, tbl + index); 538 | return ERR_NONE; 539 | } 540 | 541 | int parseJsonStringDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 542 | { 543 | char* temp = NULL; 544 | csonSetPropertyFast(output, &temp, tbl + index); 545 | return ERR_NONE; 546 | } 547 | 548 | int parseJsonIntegerDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 549 | { 550 | long long temp = 0; 551 | 552 | if (tbl[index].size != sizeof(char) && 553 | tbl[index].size != sizeof(short) && 554 | tbl[index].size != sizeof(int) && 555 | tbl[index].size != sizeof(long long)) { 556 | printf("Unsupported size(=%ld) of bool.\n", tbl[index].size); 557 | printf("Please check if the type of field %s in char/short/int/long long!\n", tbl[index].field); 558 | return ERR_OVERFLOW; 559 | } 560 | 561 | integer_val_t ret; 562 | convertInteger(temp, tbl[index].size, &ret); 563 | 564 | csonSetPropertyFast(output, &ret, tbl + index); 565 | return ERR_NONE; 566 | } 567 | 568 | int parseJsonRealDefault(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int index) 569 | { 570 | if (tbl[index].size != sizeof(double)) { 571 | printf("Unsupported size(=%ld) of bool.\n", tbl[index].size); 572 | printf("Please check if the type of field %s is double!\n", tbl[index].field); 573 | return ERR_OVERFLOW; 574 | } 575 | 576 | double temp = 0.0; 577 | csonSetPropertyFast(output, &temp, tbl + index); 578 | return ERR_NONE; 579 | } 580 | 581 | 582 | int getIntegerValue(cson_t jo_tmp, int size, integer_val_t* i) 583 | { 584 | long long temp; 585 | 586 | if (cson_typeof(jo_tmp) == CSON_INTEGER) { 587 | temp = cson_integer_value(jo_tmp); 588 | } else if (cson_typeof(jo_tmp) == CSON_TRUE) { 589 | temp = 1; 590 | } else if (cson_typeof(jo_tmp) == CSON_FALSE) { 591 | temp = 0; 592 | } else if (cson_typeof(jo_tmp) == CSON_REAL) { 593 | double tempDouble = cson_real_value(jo_tmp); 594 | if (tempDouble > LLONG_MAX || tempDouble < LLONG_MIN) { 595 | return ERR_OVERFLOW; 596 | } else { 597 | temp = tempDouble; 598 | } 599 | } else { 600 | return ERR_ARGS; 601 | } 602 | 603 | return convertInteger(temp, size, i); 604 | } 605 | 606 | int convertInteger(long long val, int size, integer_val_t* i) 607 | { 608 | int ret = checkInteger(val, size); 609 | 610 | if (ret != ERR_NONE) return ret; 611 | 612 | /* avoid error on big endian */ 613 | if (size == sizeof(char)) { 614 | i->c = val; 615 | } else if (size == sizeof(short)) { 616 | i->s = val; 617 | } else if (size == sizeof(int)) { 618 | i->i = val; 619 | } else { 620 | i->l = val; 621 | } 622 | 623 | return ERR_NONE; 624 | } 625 | 626 | int checkInteger(long long val, int size) 627 | { 628 | if (size != sizeof(char) && 629 | size != sizeof(short) && 630 | size != sizeof(int) && 631 | size != sizeof(long long)) { 632 | return ERR_OVERFLOW; 633 | } 634 | 635 | if (size == sizeof(char) && (val > CHAR_MAX || val < CHAR_MIN)) { 636 | return ERR_OVERFLOW; 637 | } else if (size == sizeof(short) && (val > SHRT_MAX || val < SHRT_MIN)) { 638 | return ERR_OVERFLOW; 639 | } else if (size == sizeof(int) && (val > INT_MAX || val < INT_MIN)) { 640 | return ERR_OVERFLOW; 641 | } else { 642 | } 643 | 644 | return ERR_NONE; 645 | } 646 | 647 | long long getIntegerValueFromPointer(void* ptr, int size) 648 | { 649 | long long ret = 0; 650 | 651 | if (!ptr) return 0; 652 | 653 | if (size == sizeof(char)) { 654 | ret = *((char*)ptr); 655 | } else if (size == sizeof(short)) { 656 | ret = *((short*)ptr); 657 | } else if (size == sizeof(int)) { 658 | ret = *((int*)ptr); 659 | } else if (size == sizeof(long long)) { 660 | ret = *((long long*)ptr); 661 | } else { 662 | printf("Unsupported size(=%d) of integer.\n", size); 663 | } 664 | 665 | return ret; 666 | } 667 | 668 | /* reflect */ 669 | const reflect_item_t* getReflexItem(const char* field, const reflect_item_t* tbl, int* pIndex) 670 | { 671 | const reflect_item_t* ret = NULL; 672 | 673 | for (int i = 0;; i++) { 674 | if (!(tbl[i].field)) break; 675 | if (strcmp(field, tbl[i].field) == 0) { 676 | ret = &(tbl[i]); 677 | 678 | if (pIndex) *pIndex = i; 679 | break; 680 | } 681 | } 682 | 683 | if (!ret) printf("Can not find field:%s.", field); 684 | 685 | return ret; 686 | } 687 | 688 | void* csonGetProperty(void* obj, const char* field, const reflect_item_t* tbl, int* pIndex) 689 | { 690 | if (!(obj && field && tbl)) return NULL; 691 | const reflect_item_t* ret = getReflexItem(field, tbl, pIndex); 692 | 693 | if (!ret) return NULL; 694 | 695 | return (void*)((char*)obj + ret->offset); 696 | } 697 | 698 | void csonSetProperty(void* obj, const char* field, void* data, const reflect_item_t* tbl) 699 | { 700 | if (!(obj && field && data && tbl)) return; 701 | 702 | const reflect_item_t* ret = getReflexItem(field, tbl, NULL); 703 | 704 | if (!ret) return; 705 | 706 | void* pDst = (void*)((char*)obj + ret->offset); 707 | memcpy(pDst, data, ret->size); 708 | return; 709 | } 710 | 711 | void csonSetPropertyFast(void* obj, const void* data, const reflect_item_t* tbl) 712 | { 713 | if (!(obj && data && tbl)) return; 714 | 715 | void* pDst = (void*)((char*)obj + tbl->offset); 716 | memcpy(pDst, data, tbl->size); 717 | return; 718 | } 719 | 720 | void csonLoopProperty(void* pData, const reflect_item_t* tbl, loop_func_t func) 721 | { 722 | int i = 0; 723 | while (1) { 724 | if (!tbl[i].field) break; 725 | 726 | char* pProperty = (char*)pData + tbl[i].offset; 727 | if (tbl[i].type == CSON_ARRAY) { 728 | int countIndex = -1; 729 | void* ptr = csonGetProperty(pData, tbl[i].arrayCountField, tbl, &countIndex); 730 | 731 | if (ptr == NULL || countIndex == -1) { 732 | continue; 733 | } 734 | long long size = getIntegerValueFromPointer(ptr, tbl[countIndex].size); 735 | 736 | for (long long j = 0; j < size; j++) { 737 | csonLoopProperty(*((char**)pProperty) + j * tbl[i].arrayItemSize, tbl[i].reflect_tbl, func); 738 | } 739 | } else if (tbl[i].type == CSON_OBJECT) { 740 | csonLoopProperty(pProperty, tbl[i].reflect_tbl, func); 741 | } 742 | 743 | func(pProperty, tbl + i); 744 | 745 | i++; 746 | } 747 | } 748 | 749 | static void* printPropertySub(void* pData, const reflect_item_t* tbl) 750 | { 751 | if (tbl->type == CSON_ARRAY || tbl->type == CSON_OBJECT) return NULL; 752 | 753 | if (tbl->type == CSON_INTEGER || tbl->type == CSON_TRUE || tbl->type == CSON_FALSE) printf("%s:%d\n", tbl->field, *(int*)pData); 754 | 755 | if (tbl->type == CSON_REAL) printf("%s:%f\n", tbl->field, *(double*)pData); 756 | 757 | if (tbl->type == CSON_STRING) printf("%s:%s\n", tbl->field, *((char**)pData)); 758 | 759 | return NULL; 760 | } 761 | 762 | static void* freePointerSub(void* pData, const reflect_item_t* tbl) 763 | { 764 | if (tbl->type == CSON_ARRAY || tbl->type == CSON_STRING) { 765 | //printf("free field %s.\n", tbl->field); 766 | free(*(void**)pData); 767 | *(void**)pData = NULL; 768 | } 769 | return NULL; 770 | } 771 | 772 | void csonPrintProperty(void* pData, const reflect_item_t* tbl) 773 | { 774 | /* 调用loopProperty迭代结构体中的属性,完成迭代输出属性值 */ 775 | csonLoopProperty(pData, tbl, printPropertySub); 776 | } 777 | 778 | void csonFreePointer(void* list, const reflect_item_t* tbl) 779 | { 780 | /* 调用loopProperty迭代结构体中的属性,释放字符串和数组申请的内存空间 */ 781 | csonLoopProperty(list, tbl, freePointerSub); 782 | } --------------------------------------------------------------------------------