Skip to content

Commit f7d86f1

Browse files
committed
Added JSONUtils::updatePointer
1 parent 6e20e3f commit f7d86f1

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

modules/juce_core/json/juce_JSONUtils.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,74 @@ std::optional<var> JSONUtils::setPointer (const var& v,
124124
return {};
125125
}
126126

127+
bool JSONUtils::updatePointer (var& v, String pointer, const var& newValue)
128+
{
129+
if (pointer.isEmpty())
130+
return false;
131+
132+
if (! pointer.startsWith ("/"))
133+
{
134+
// This is not a well-formed JSON pointer
135+
jassertfalse;
136+
return {};
137+
}
138+
139+
const auto findResult = pointer.indexOfChar (1, '/');
140+
const auto pos = findResult < 0 ? pointer.length() : findResult;
141+
const String head (pointer.begin() + 1, pointer.begin() + pos);
142+
const String tail (pointer.begin() + pos, pointer.end());
143+
144+
const auto unescaped = head.replace ("~1", "/").replace ("~0", "~");
145+
146+
if (auto* object = v.getDynamicObject())
147+
{
148+
if (tail.isEmpty())
149+
{
150+
object->setProperty (unescaped, newValue);
151+
return true;
152+
}
153+
154+
auto v = object->getProperty (unescaped);
155+
return updatePointer (v, tail, newValue);
156+
}
157+
else if (auto* array = v.getArray())
158+
{
159+
const auto index = [&]() -> size_t
160+
{
161+
if (unescaped == "-")
162+
return (size_t) array->size();
163+
164+
if (unescaped == "0")
165+
return 0;
166+
167+
if (! unescaped.startsWith ("0"))
168+
return (size_t) unescaped.getLargeIntValue();
169+
170+
return std::numeric_limits<size_t>::max();
171+
}();
172+
173+
if (tail.isEmpty())
174+
{
175+
if (isPositiveAndBelow (index, array->size()))
176+
{
177+
array->set (int (index), newValue);
178+
return true;
179+
}
180+
181+
if (index == array->size())
182+
{
183+
array->add (newValue);
184+
return true;
185+
}
186+
}
187+
188+
auto v = (*array)[(int) index];
189+
return updatePointer (v, tail, newValue);
190+
}
191+
192+
return false;
193+
}
194+
127195
var JSONUtils::getPointer (const var& v, String pointer, const var& defaultValue)
128196
{
129197
if (pointer.isEmpty())

modules/juce_core/json/juce_JSONUtils.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ struct JSONUtils
5757
*/
5858
static std::optional<var> setPointer (const var& v, String pointer, const var& newValue);
5959

60+
/** Given a JSON array/object 'v', a string representing a JSON pointer,
61+
and a new property value 'newValue', updates 'v' where the
62+
property or array index referenced by the pointer has been set to 'newValue'.
63+
64+
If the pointer cannot be followed, due to referencing missing array indices
65+
or fields, then this returns false.
66+
67+
For more details, check the JSON Pointer RFC 6901:
68+
https://datatracker.ietf.org/doc/html/rfc6901
69+
*/
70+
static bool updatePointer (var& v, String pointer, const var& newValue);
71+
6072
/** Given a JSON array/object 'v', a string representing a JSON pointer,
6173
returns the value of the property or array index referenced by the pointer
6274

0 commit comments

Comments
 (0)