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();
101 if ((
int) index ==
copied.size())
115bool JSONUtils::deepEqual (
const var& a,
const var& b)
124 if (! y.hasProperty (key))
127 if (! deepEqual (value, y.getProperty (key)))
134 if (
auto* i = a.getDynamicObject())
135 if (
auto* j = b.getDynamicObject())
136 return compareObjects (*i, *j);
140 return std::equal (i->begin(), i->end(), j->begin(), j->end(), [] (
const var& x,
const var& y) {
return deepEqual (x, y); });
149class JSONUtilsTests final :
public UnitTest
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] }
202 expect (deepEqual (a, b), text);
214static JSONUtilsTests jsonUtilsTests;
Represents a dynamically implemented object.
NamedValueSet & getProperties() noexcept
Returns the NamedValueSet that holds the object's properties.
Represents a string identifier, designed for accessing properties by name.
static Result parse(const String &text, var &parsedResult)
Parses a string of JSON-formatted text, and returns a result code containing any parse errors.
static String toString(const var &objectToFormat, bool allOnOneLine=false, int maximumDecimalPlaces=15)
Returns a string which contains a JSON-formatted representation of the var object.
int size() const noexcept
Returns the total number of values that the set contains.
CharPointerType begin() const
Returns an iterator pointing at the beginning of the string.
int indexOfChar(juce_wchar characterToLookFor) const noexcept
Searches for a character inside this string.
int length() const noexcept
Returns the number of characters in the string.
bool isEmpty() const noexcept
Returns true if the string contains no characters.
bool startsWith(StringRef text) const noexcept
Tests whether the string begins with another string.
CharPointerType end() const
Returns an iterator pointing at the terminating null of the string.
String replace(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
Replaces all occurrences of a substring with another string.
This is a base class for classes that perform a unit test.
void beginTest(const String &testName)
Tells the system that a new subsection of tests is beginning.
void expect(bool testResult, const String &failureMessage=String())
Checks that the result of a test is true, and logs this result.
virtual void runTest()=0
Implement this method in your subclass to actually run your tests.
A variant class, that can be used to hold a range of primitive values.
Array< var > * getArray() const noexcept
If this variant holds an array, this provides access to it.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
static std::optional< var > setPointer(const var &v, String pointer, const var &newValue)
Given a JSON array/object 'v', a string representing a JSON pointer, and a new property value 'newVal...
static bool deepEqual(const var &a, const var &b)
Returns true if and only if the contents of a match the contents of b.
static var makeObject(const std::map< Identifier, var > &source)
Converts the provided key/value pairs into a JSON object.
static var makeObjectWithKeyFirst(const std::map< Identifier, var > &source, Identifier key)
Converts the provided key/value pairs into a JSON object with the provided key at the first position ...