#include #include static Tcl_ObjCmdProc json2dict; Tcl_AppInitProc Json2dict_Init; static Tcl_Obj * value2obj(Tcl_Interp *I, struct json_object *jso) { Tcl_Obj *result, *key, *value; int len; struct array_list *ar; switch (json_object_get_type(jso)) { case json_type_object: result = Tcl_NewDictObj(); json_object_object_foreach(jso, k, v) { key = Tcl_NewStringObj(k, -1); value = value2obj(I, v); Tcl_DictObjPut(I, result, key, value); json_object_object_del(jso, k); } return result; case json_type_null: return Tcl_NewObj(); case json_type_boolean: return Tcl_NewBooleanObj(json_object_get_boolean(jso)); case json_type_double: return Tcl_NewDoubleObj(json_object_get_double(jso)); case json_type_int: return Tcl_NewLongObj(json_object_get_int64(jso)); case json_type_array: ar = json_object_get_array(jso); result = Tcl_NewListObj(0, NULL); for (len = 0; len < ar->length; len++) Tcl_ListObjAppendElement(I, result, value2obj(I, ar->array[len])); return result; case json_type_string: len = json_object_get_string_len(jso); return Tcl_NewStringObj(json_object_get_string(jso), len); } return NULL; /* unreachable */ } int json2dict(ClientData cd, Tcl_Interp *I, int objc, Tcl_Obj * const *objv) { struct json_tokener *tok; enum json_tokener_error jerr; struct json_object *parsed; const char *text; int len; if (objc != 2) { Tcl_WrongNumArgs(I, 1, objv, "JSON-text"); return TCL_ERROR; } text = Tcl_GetStringFromObj(objv[1], &len); tok = json_tokener_new(); parsed = json_tokener_parse_ex(tok, text, len); if (parsed == NULL) { jerr = json_tokener_get_error(tok); Tcl_SetResult(I, (void *)json_tokener_error_desc(jerr), TCL_STATIC); json_tokener_free(tok); return TCL_ERROR; } json_tokener_free(tok); Tcl_SetObjResult(I, value2obj(I, parsed)); json_object_put(parsed); return TCL_OK; } int Json2dict_Init(Tcl_Interp *I) { Tcl_CreateObjCommand(I, "json2dict", json2dict, NULL, NULL); return Tcl_PkgProvide(I, "json_bin", "1.0"); }