JSON
JSONObjectIterator
// EXAMPLE
SerialLogHandler logHandler;
void setup() {
Particle.subscribe("jsonTest", subscriptionHandler);
}
void subscriptionHandler(const char *event, const char *data) {
JSONValue outerObj = JSONValue::parseCopy(data);
JSONObjectIterator iter(outerObj);
while(iter.next()) {
Log.info("key=%s value=%s",
(const char *) iter.name(),
(const char *) iter.value().toString());
}
}
// TEST EVENT
$ particle publish jsonTest '{"a":123,"b":"testing"}'
// LOG
0000068831 [app] INFO: key=a value=123
0000068831 [app] INFO: key=b value=testing
In order to access key/value pairs in a JSON object, you just create a JSONObjectIterator
from the JSONValue
.
The basic flow is:
- Create a
JSONObjectIterator
from aJSONValue
. - Call
iter.next()
. This must be done before accessing the first value, and to access each subsequent value. When it returns false, there are no more elements. It's possible fornext()
return false on the first call for an empty object. - Use
iter.name()
anditer.value()
to get the key name and value.
// EXAMPLE
JSONValue outerObj = JSONValue::parseCopy(
"{\"a\":123,\"b\":\"test\",\"c\":true}");
JSONObjectIterator iter(outerObj);
while(iter.next()) {
if (iter.name() == "a") {
Log.trace("a=%d",
iter.value().toInt());
}
else
if (iter.name() == "b") {
Log.trace("b=%s",
(const char *) iter.value().toString());
}
else
if (iter.name() == "c") {
Log.trace("c=%d",
iter.value().toBool());
}
else {
Log.trace("unknown key %s",
(const char *)iter.name());
}
}
// LOG
0000242555 [app] TRACE: a=123
0000242555 [app] TRACE: b=test
0000242555 [app] TRACE: c=1
Since there is no way to find an element by its key name, you typically iterate the object and compare the name like this:
You should not rely on the ordering of keys in a JSON object. While in this simple example, the keys will always be in the order a, b, c, when JSON objects are manipulated by server-based code, the keys can sometimes be reordered. The name-based check here assures compatibility even if reordered. Arrays will always stay in the same order.
JSONObjectIterator::JSONObjectIterator(const JSONValue &value)
// PROTOTYPE
explicit JSONObjectIterator(const JSONValue &value);
Construct an iterator from a JSONValue
. This can be the whole object, or you can use it to iterate an object within the key of another object.
JSONObjectIterator::next()
// PROTOTYPE
bool next();
Call next()
before accessing name()
and value()
. Then each subsequent call will get the next pair. When it returns false, there are no elements left. It's possible for next()
to return false on the first call if the object has no key/value pairs.
There is no rewind function to go back to the beginning. To start over, construct a new JSONObjectIterator
from the JSONValue
again.
JSONObjectIterator::name()
// PROTOTYPE
JSONString name() const;
Returns the name of the current name/value pair in the object. The name must be 7-bit ASCII but can contain characters that require escaping (like double quotes and backslash). To get a const char *
you can use iter.name().data()
.
JSONObjectIterator::value()
// PROTOTYPE
JSONValue value() const;
Returns the current value of the name/value pair in the object.
You will typically use methods of JSONValue
like toInt()
, toBool()
, toDouble()
, and toString()
to get useful values. For example:
iter.value().toInt()
: Returns a signed 32-bit int.iter.value().toDouble()
: Returns a 64-bit double.iter.value().toString().data()
: Returns aconst char *
. You can assign this to aString
to copy the value, if desired.
JSONObjectIterator::count()
// PROTOTYPE
size_t count() const;
Returns the count of the number of remaining key/value pairs. As you call next()
this value will decrease.