28 auto result = std::make_unique<DynamicObject>();
30 for (
const auto& [name, value] : source)
31 result->setProperty (name, value);
33 return var (result.release());
39 auto result = std::make_unique<DynamicObject>();
41 if (
const auto iter = source.find (key);
iter != source.end())
42 result->setProperty (key,
iter->second);
44 for (
const auto& [name, value] : source)
46 result->setProperty (name, value);
48 return var (result.release());
72 if (
auto*
object = v.getDynamicObject())
76 auto cloned =
object->clone();
83 const auto index = [&]() ->
size_t
86 return (
size_t) array->size();
92 return (
size_t)
unescaped.getLargeIntValue();
94 return std::numeric_limits<size_t>::max();
101 if ((
int) index ==
copied.size())
104 if (isPositiveAndBelow (index,
copied.size()))
115bool JSONUtils::deepEqual (
const var& a,
const var& b)
119 if (
x.getProperties().size() != y.getProperties().size())
122 for (
const auto& [key, value] :
x.getProperties())
124 if (! y.hasProperty (key))
127 if (! deepEqual (value, y.getProperty (key)))
134 if (
auto* i = a.getDynamicObject())
135 if (
auto*
j = b.getDynamicObject())
140 return std::equal (i->begin(), i->end(),
j->begin(),
j->end(), [] (
const var&
x,
const var& y) {
return deepEqual (
x, y); });
154 void runTest()
override
156 beginTest (
"JSON pointers");
158 const auto obj = JSON::parse (R
"({ "name": "PIANO 4"
160 , "lfoWaveform": "triangle"
161 , "pitchEnvelope": { "rates": [94,67,95,60], "levels": [50,50,50,50] }
163 expectDeepEqual (JSONUtils::setPointer (obj, "",
"hello world"), var (
"hello world"));
164 expectDeepEqual (JSONUtils::setPointer (obj,
"/lfoWaveform/foobar",
"str"), std::nullopt);
165 expectDeepEqual (JSONUtils::setPointer (JSON::parse (R
"({"foo":0,"bar":1})"), "/foo", 2), JSON::parse (R
"({"foo":2,"bar":1})"));
166 expectDeepEqual (JSONUtils::setPointer (JSON::parse (R"({"foo":0,"bar":1})"), "/baz", 2), JSON::parse (R
"({"foo":0,"bar":1,"baz":2})"));
167 expectDeepEqual (JSONUtils::setPointer (JSON::parse (R"({"foo":{},"bar":{}})"), "/foo/bar", 2), JSON::parse (R
"({"foo":{"bar":2},"bar":{}})"));
168 expectDeepEqual (JSONUtils::setPointer (obj, "/pitchEnvelope/rates/01",
"str"), std::nullopt);
169 expectDeepEqual (JSONUtils::setPointer (obj,
"/pitchEnvelope/rates/10",
"str"), std::nullopt);
170 expectDeepEqual (JSONUtils::setPointer (obj,
"/lfoSpeed", 10), JSON::parse (R
"({ "name": "PIANO 4"
172 , "lfoWaveform": "triangle"
173 , "pitchEnvelope": { "rates": [94,67,95,60], "levels": [50,50,50,50] }
175 expectDeepEqual (JSONUtils::setPointer (JSON::parse (R"([0,1,2])"), "/0",
"bang"), JSON::parse (R
"(["bang",1,2])"));
176 expectDeepEqual (JSONUtils::setPointer (JSON::parse (R"([0,1,2])"), "/0",
"bang"), JSON::parse (R
"(["bang",1,2])"));
177 expectDeepEqual (JSONUtils::setPointer (JSON::parse (R"({"/":"fizz"})"), "/~1",
"buzz"), JSON::parse (R
"({"/":"buzz"})"));
178 expectDeepEqual (JSONUtils::setPointer (JSON::parse (R"({"~":"fizz"})"), "/~0",
"buzz"), JSON::parse (R
"({"~":"buzz"})"));
179 expectDeepEqual (JSONUtils::setPointer (obj, "/pitchEnvelope/rates/0", 80), JSON::parse (R
"({ "name": "PIANO 4"
181 , "lfoWaveform": "triangle"
182 , "pitchEnvelope": { "rates": [80,67,95,60], "levels": [50,50,50,50] }
184 expectDeepEqual (JSONUtils::setPointer (obj, "/pitchEnvelope/levels/0", 80), JSON::parse (R
"({ "name": "PIANO 4"
186 , "lfoWaveform": "triangle"
187 , "pitchEnvelope": { "rates": [94,67,95,60], "levels": [80,50,50,50] }
189 expectDeepEqual (JSONUtils::setPointer (obj, "/pitchEnvelope/levels/-", 100), JSON::parse (R
"({ "name": "PIANO 4"
191 , "lfoWaveform": "triangle"
192 , "pitchEnvelope": { "rates": [94,67,95,60], "levels": [50,50,50,50,100] }
197 void expectDeepEqual (
const std::optional<var>& a,
const std::optional<var>& b)
199 const auto text = a.has_value() && b.has_value()
200 ? JSON::toString (*a) +
" != " + JSON::toString (*b)
202 expect (deepEqual (a, b), text);
205 static bool deepEqual (
const std::optional<var>& a,
const std::optional<var>& b)
207 if (a.has_value() && b.has_value())
208 return JSONUtils::deepEqual (*a, *b);
214static JSONUtilsTests jsonUtilsTests;
CharPointerType begin() const
int indexOfChar(juce_wchar characterToLookFor) const noexcept
int length() const noexcept
bool isEmpty() const noexcept
bool startsWith(StringRef text) const noexcept
CharPointerType end() const
String replace(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
Array< var > * getArray() const noexcept
static std::optional< var > setPointer(const var &v, String pointer, const var &newValue)
static var makeObject(const std::map< Identifier, var > &source)
static var makeObjectWithKeyFirst(const std::map< Identifier, var > &source, Identifier key)