static mrb_value json_value_to_mrb_value(mrb_state* mrb, JSON_Value* value) { ARENA_SAVE; switch (json_value_get_type(value)) { case JSONError: case JSONNull: return mrb_nil_value(); case JSONString: return mrb_str_new_cstr(mrb, json_value_get_string(value)); case JSONNumber: return mrb_float_value(json_value_get_number(value)); case JSONObject: { mrb_value hash = mrb_hash_new(mrb); JSON_Object* object = json_value_get_object(value); size_t count = json_object_get_count(object); int n; for (n = 0; n < count; n++) { const char* name = json_object_get_name(object, n); mrb_hash_set(mrb, hash, mrb_str_new_cstr(mrb, name), json_value_to_mrb_value(mrb, json_object_get_value(object, name))); } return hash; } case JSONArray: { mrb_value ary; ary = mrb_ary_new(mrb); JSON_Array* array = json_value_get_array(value); size_t count = json_array_get_count(array); int n; for (n = 0; n < count; n++) { JSON_Value* elem = json_array_get_value(array, n); mrb_ary_push(mrb, ary, json_value_to_mrb_value(mrb, elem)); } return ary; } case JSONBoolean: if (json_value_get_boolean(value)) { return mrb_true_value(); } return mrb_false_value(); default: mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } return mrb_nil_value(); }
static mrb_value mrb_json_parse(mrb_state *mrb, mrb_value self) { mrb_value value; JSON_Value *root_value; mrb_value json = mrb_nil_value(); mrb_get_args(mrb, "S", &json); root_value = json_parse_string(mrb_str_to_cstr(mrb, json)); if (!root_value) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid json"); } value = json_value_to_mrb_value(mrb, root_value); json_value_free(root_value); return value; }
static mrb_value mrb_json_parse(mrb_state *mrb, mrb_value self) { mrb_value json = mrb_nil_value(); mrb_get_args(mrb, "o", &json); if (!mrb_string_p(json)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } JSON_Value *root_value = json_parse_string(RSTRING_PTR(json)); if (!root_value) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid json"); } mrb_value value = json_value_to_mrb_value(mrb, root_value); json_value_free(root_value); return value; }
static mrb_value json_value_to_mrb_value(mrb_state* mrb, JSON_Value* value) { mrb_value ret; switch (json_value_get_type(value)) { case JSONError: case JSONNull: ret = mrb_nil_value(); break; case JSONString: ret = mrb_str_new_cstr(mrb, json_value_get_string(value)); break; case JSONNumber: { double d = json_value_get_number(value); if (floor(d) == d) { ret = mrb_fixnum_value(d); } else { ret = mrb_float_value(mrb, d); } } break; case JSONObject: { mrb_value hash = mrb_hash_new(mrb); JSON_Object* object = json_value_get_object(value); size_t count = json_object_get_count(object); size_t n; for (n = 0; n < count; n++) { int ai = mrb_gc_arena_save(mrb); const char* name = json_object_get_name(object, n); mrb_hash_set(mrb, hash, mrb_str_new_cstr(mrb, name), json_value_to_mrb_value(mrb, json_object_get_value(object, name))); mrb_gc_arena_restore(mrb, ai); } ret = hash; } break; case JSONArray: { mrb_value ary; JSON_Array* array; size_t n, count; ary = mrb_ary_new(mrb); array = json_value_get_array(value); count = json_array_get_count(array); for (n = 0; n < count; n++) { int ai = mrb_gc_arena_save(mrb); JSON_Value* elem = json_array_get_value(array, n); mrb_ary_push(mrb, ary, json_value_to_mrb_value(mrb, elem)); mrb_gc_arena_restore(mrb, ai); } ret = ary; } break; case JSONBoolean: if (json_value_get_boolean(value)) ret = mrb_true_value(); else ret = mrb_false_value(); break; default: mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } return ret; }