Here is some code that might be a starting point. It’s still an early on in it’s implementation, in that I just codified it a few weeks ago, to help me process JSON input. But I think the basic ‘tree walking’ structure of it will help you build some code to make ValueTree’s.
VarHelpers.h
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
namespace VarHelpers
{
void addProperty (const var& object, String key, var value);
var addSection (const var& object, String key);
void forEachSection (const var& object, std::function<void (String key, const var& section)> sectionCallback);
void forEachProperty (const var& object, std::function<void (String key, const var& property)> propertyCallback);
String getVarAttribString (const var& theVar);
void dumpVar (const var& theVar);
const var& getSection (const var& theVar, Identifier key);
template<class T>
bool hasProperty (const var& theVar, Identifier property)
{
if (theVar.hasProperty (property))
{
if constexpr (std::is_same_v<T, int>)
{
if (theVar[property].isInt ())
return true;
}
else if constexpr (std::is_same_v<T, int64>)
{
if (theVar[property].isInt64 ())
return true;
}
else if constexpr (std::is_same_v<T, bool>)
{
if (theVar[property].isBool ())
return true;
}
else if constexpr (std::is_same_v<T, double>)
{
if (theVar[property].isDouble ())
return true;
}
else if constexpr (std::is_same_v<T, String>)
{
if (theVar[property].isString ())
return true;
}
else if constexpr (std::is_same_v<T, Array<var>>)
{
if (theVar[property].isArray ())
return true;
}
}
return false;
}
template<class T>
T getProperty (const var& theVar, Identifier property)
{
if constexpr (std::is_same_v<T, String>)
return theVar[property].toString ();
else
return (T)theVar[property];
}
};
VarHelpers.cpp
#include "VarHelpers.h"
namespace VarHelpers
{
void addProperty (const var& object, String key, var value)
{
if (!key.isEmpty () && object.isObject ())
object.getDynamicObject ()->setProperty (key, value);
};
var addSection (const var& object, String key)
{
if (!key.isEmpty () && object.isObject ())
{
var newSection (new DynamicObject);
addProperty (object, key, newSection);
return newSection;
}
return {};
}
void forEachSection (const var& object, std::function<void (String key, const var& section)> sectionCallback)
{
if (object.isObject ())
{
const auto dynamicObject = object.getDynamicObject ();
const auto namedPropertySet = dynamicObject->getProperties ();
for (const auto& namedProperty : namedPropertySet)
{
if (namedProperty.value.isObject ())
sectionCallback (namedProperty.name.toString (), namedProperty.value);
}
}
}
void forEachProperty (const var& object, std::function<void (String key, const var& property)> propertyCallback)
{
if (object.isObject ())
{
const auto dynamicObject = object.getDynamicObject ();
const auto namedPropertySet = dynamicObject->getProperties ();
for (const auto& namedProperty : namedPropertySet)
{
if (!namedProperty.value.isObject ())
propertyCallback (namedProperty.name.toString (), namedProperty.value);
}
}
}
String getVarAttribString (const var& theVar)
{
if (theVar.isVoid ())
return "void";
else if (theVar.isInt ())
return "int";
else if (theVar.isInt64 ())
return "int64";
else if (theVar.isBool ())
return "bool";
else if (theVar.isDouble ())
return "double";
else if (theVar.isString ())
return "String";
else if (theVar.isObject ())
return "Object";
else if (theVar.isArray ())
return "Array";
else if (theVar.isBinaryData ())
return "BinaryData";
else if (theVar.isMethod ())
return "Method";
return "unknown";
};
void dumpVar (const var& theVar)
{
if (theVar.isObject())
{
std::function<void (const var& theVar, String name, int indentLevel)> dumpSections = [&dumpSections](const var& theVar, String name, int indentLevel)
{
Logger::outputDebugString (String (std::string (indentLevel, ' ')) + String ("<") + (name.isEmpty () ? String ("noname") : name) + String (">"));
VarHelpers::forEachProperty (theVar, [indentLevel](String key, const var& value)
{
Logger::outputDebugString (String (std::string (indentLevel + 1, ' ')) + key + " : " + VarHelpers::getVarAttribString (value));
});
VarHelpers::forEachSection (theVar, [&dumpSections, indentLevel](String key, const var& value)
{
dumpSections (value, key, indentLevel + 1);
});
};
dumpSections (theVar, "", 0);
}
else
{
Logger::outputDebugString ("var type : " + VarHelpers::getVarAttribString (theVar));
}
}
const var emptyVar;
const var& getSection (const var& theVar, Identifier key)
{
if (const auto& section = theVar[key]; section.isObject ())
return section;
else
return emptyVar;
}
};