mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
Add object_from_json as a non-breaking alternative to from_json that returns a Dynamic_Object instead of a Map, enabling dot-access syntax on JSON fields (e.g. obj.name instead of obj["name"]). Nested JSON objects become nested Dynamic_Objects. Also add map_to_object and object_to_map for Python-style interconversion between maps and objects. Co-authored-by: leftibot <leftibot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
07d62aae99
commit
362e93fb29
@ -2,13 +2,17 @@
|
||||
#define CHAISCRIPT_SIMPLEJSON_WRAP_HPP
|
||||
|
||||
#include "json.hpp"
|
||||
#include "../dispatchkit/dynamic_object.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class json_wrap {
|
||||
public:
|
||||
static Module &library(Module &m) {
|
||||
m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
||||
m.add(chaiscript::fun([](const std::string &t_str) { return object_from_json(t_str); }), "object_from_json");
|
||||
m.add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
||||
m.add(chaiscript::fun(&json_wrap::map_to_object), "map_to_object");
|
||||
m.add(chaiscript::fun(&json_wrap::object_to_map), "object_to_map");
|
||||
|
||||
return m;
|
||||
}
|
||||
@ -57,6 +61,63 @@ namespace chaiscript {
|
||||
}
|
||||
}
|
||||
|
||||
static Boxed_Value object_from_json(const json::JSON &t_json) {
|
||||
switch (t_json.JSONType()) {
|
||||
case json::JSON::Class::Null:
|
||||
return Boxed_Value();
|
||||
case json::JSON::Class::Object: {
|
||||
auto obj = dispatch::Dynamic_Object("JSON_Object");
|
||||
|
||||
for (const auto &p : t_json.object_range()) {
|
||||
obj.get_attr(p.first) = object_from_json(p.second);
|
||||
}
|
||||
|
||||
return Boxed_Value(std::move(obj));
|
||||
}
|
||||
case json::JSON::Class::Array: {
|
||||
std::vector<Boxed_Value> vec;
|
||||
|
||||
for (const auto &p : t_json.array_range()) {
|
||||
vec.emplace_back(object_from_json(p));
|
||||
}
|
||||
|
||||
return Boxed_Value(vec);
|
||||
}
|
||||
case json::JSON::Class::String:
|
||||
return Boxed_Value(t_json.to_string());
|
||||
case json::JSON::Class::Floating:
|
||||
return Boxed_Value(t_json.to_float());
|
||||
case json::JSON::Class::Integral:
|
||||
return Boxed_Value(t_json.to_int());
|
||||
case json::JSON::Class::Boolean:
|
||||
return Boxed_Value(t_json.to_bool());
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown JSON type");
|
||||
}
|
||||
|
||||
static Boxed_Value object_from_json(const std::string &t_json) {
|
||||
try {
|
||||
return object_from_json(json::JSON::Load(t_json));
|
||||
} catch (const std::out_of_range &) {
|
||||
throw std::runtime_error("Unparsed JSON input");
|
||||
}
|
||||
}
|
||||
|
||||
static Boxed_Value map_to_object(const std::map<std::string, Boxed_Value> &t_map) {
|
||||
auto obj = dispatch::Dynamic_Object("JSON_Object");
|
||||
|
||||
for (const auto &p : t_map) {
|
||||
obj.get_attr(p.first) = p.second;
|
||||
}
|
||||
|
||||
return Boxed_Value(std::move(obj));
|
||||
}
|
||||
|
||||
static std::map<std::string, Boxed_Value> object_to_map(const dispatch::Dynamic_Object &t_obj) {
|
||||
return t_obj.get_attrs();
|
||||
}
|
||||
|
||||
static std::string to_json(const Boxed_Value &t_bv) { return to_json_object(t_bv).dump(); }
|
||||
|
||||
static json::JSON to_json_object(const Boxed_Value &t_bv) {
|
||||
|
||||
6
unittests/object_from_json_1.chai
Normal file
6
unittests/object_from_json_1.chai
Normal file
@ -0,0 +1,6 @@
|
||||
// object_from_json: returns Dynamic_Object with dot-access on JSON fields
|
||||
var obj = object_from_json("{\"name\":\"ChaiScript\",\"version\":6,\"active\":true}")
|
||||
assert_equal(obj.name, "ChaiScript")
|
||||
assert_equal(obj.version, 6)
|
||||
assert_equal(obj.active, true)
|
||||
assert_equal(obj.get_type_name(), "JSON_Object")
|
||||
3
unittests/object_from_json_2.chai
Normal file
3
unittests/object_from_json_2.chai
Normal file
@ -0,0 +1,3 @@
|
||||
// object_from_json: nested objects become nested Dynamic_Objects
|
||||
var obj = object_from_json("{\"outer\":{\"inner\":42}}")
|
||||
assert_equal(obj.outer.inner, 42)
|
||||
3
unittests/object_from_json_3.chai
Normal file
3
unittests/object_from_json_3.chai
Normal file
@ -0,0 +1,3 @@
|
||||
// object_from_json: arrays remain as vectors
|
||||
var obj = object_from_json("{\"items\":[1,2,3]}")
|
||||
assert_equal(obj.items, [1,2,3])
|
||||
9
unittests/object_from_json_4.chai
Normal file
9
unittests/object_from_json_4.chai
Normal file
@ -0,0 +1,9 @@
|
||||
// object_to_map and map_to_object conversions
|
||||
var m = ["a": 1, "b": "hello"]
|
||||
var obj = map_to_object(m)
|
||||
assert_equal(obj.a, 1)
|
||||
assert_equal(obj.b, "hello")
|
||||
|
||||
var m2 = object_to_map(obj)
|
||||
assert_equal(m2["a"], 1)
|
||||
assert_equal(m2["b"], "hello")
|
||||
6
unittests/object_from_json_5.chai
Normal file
6
unittests/object_from_json_5.chai
Normal file
@ -0,0 +1,6 @@
|
||||
// object_from_json roundtrip through to_json
|
||||
var json_str = "{\"key\":\"value\"}"
|
||||
var obj = object_from_json(json_str)
|
||||
var result = to_json(obj)
|
||||
var obj2 = object_from_json(result)
|
||||
assert_equal(obj2.key, "value")
|
||||
Loading…
x
Reference in New Issue
Block a user