SOLVED How to read JSON using Maxon API?

Would someone be able to provide a working example of how to use the Maxon API to read in some simple json like the following?

There doesn't seem to be any documentation that shows how to iterate over and extract this type of data from a DataDictionary. A complete working example would be great to have.

I am trying to use the Maxon API to read in the following JSON but I can't figure out how to get all the data from the returned DataDictionary.

{
	"a": [{
			"b": "bbb",
			"c": "ccc"
		},
		{
			"d": "ddd",
			"e": "eee"
		}
	]
}

Hi kent,

we have this thread where you asked the question.

Following an example about how to read the data from a json like that. I've also add the case when you have the same keys in your json so you can loop over the elements.

There is no way of accessing directly a element in the json file.

#include "maxon/apibase.h"
#include "maxon/errorbase.h"
#include "maxon/errortypes.h"
#include "maxon/parser.h"
#include "maxon/application.h"

#include "c4d_general.h"


// This function read a json file and return the content as a datadictionary.
static maxon::Result<const maxon::DataDictionary> ReadJSONFile(const maxon::Url& jsonfFile)
{
	iferr_scope;
	CheckArgument(jsonfFile.IoDetect() != maxon::IODETECT::NONEXISTENT, "File doesn't exist"_s);
	
	// Create the parser for the json file and read it.
	maxon::BaseArray<maxon::DataDictionary> jsonArray;
	maxon::ParserRef parser = maxon::ParserClasses::JsonParser().Create() iferr_return;
	parser.Read(jsonfFile, maxon::PARSERFLAGS::NONE, maxon::GetUtf8DefaultDecoder(), jsonArray) iferr_return;
	if (jsonArray.IsPopulated())
		return jsonArray[0];

	return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Json file couldn't be read"_s);
}


static maxon::Result<void> pc13625(BaseDocument* doc)
{

	iferr_scope;
	/*
	 this function read the following json file:
	 
	 {
		 "a": [{
				 "b": "bbb",
				 "c": "ccc"
			 },
			 {
				 "d": "ddd",
				 "e": "eee"
			 }
		 ],


		 "b" : [{
			 "name" : "one",
			 "value" : 1
			 },
			 {
			 "name" : "two",
			 "value" : 2,
			 "valueasfloat" : 2.0
			 }
		 ]
	 }
	 
	 The element in the array "a" do not share the same keys. The first one have b and c, the second d and e. So we have to access all element one by one.
	 
	 In the array "b" the elements share the same keys so we can loop over them.
	 */
	
	
	
	const maxon::Url myJsonFile = maxon::Application::GetUrl(maxon::APPLICATION_URLTYPE::CURRENT_MODULE_DIR).Append("res"_s).Append("jsonexample.json"_s) iferr_return;

	
	const maxon::DataDictionary content = ReadJSONFile(myJsonFile) iferr_return;

	MAXON_SCOPE
	{
		// Reading array "a" we can't loop all the element because they have different keys.
		maxon::BaseArray<maxon::Data> arrayA = content.Get<maxon::BaseArray<maxon::Data>>("a"_s) iferr_return;
		const  maxon::Data& firstElement = arrayA[0];
		// we know the elements in the array are dictionary so we can convert Data to Dictionary
		maxon::DataDictionary bAndc = firstElement.Convert<maxon::DataDictionary>() iferr_return;
		const String b = bAndc.Get<String>("b"_s) iferr_return;
		const String c = bAndc.Get<String>("c"_s) iferr_return;
		
		const  maxon::Data& secondElement = arrayA[1];
		maxon::DataDictionary dAnde = secondElement.Convert<maxon::DataDictionary>() iferr_return;
		const String d = dAnde.Get<String>("d"_s) iferr_return;
		const String e = dAnde.Get<String>("e"_s) iferr_return;

		ApplicationOutput("value in the json are b:@ c:@ d:@ e:@", b, c, d, e);
	}
	
	MAXON_SCOPE
	{
		// reading array "B" we can loop over all elements because they share the same key.
		maxon::BaseArray<maxon::Data> arrayB = content.Get<maxon::BaseArray<maxon::Data>>("b"_s) iferr_return;
		for (maxon::Data& element : arrayB)
		{
			maxon::DataDictionary dict = element.Convert<maxon::DataDictionary>() iferr_return;
			const String name = dict.Get<String>("name"_s) iferr_return;
			const Int value = dict.Get<Int>("value"_s) iferr_return;
			
			// As the value as float is optionnal, we need a different path if the value doesn't exist.

			iferr (const Float valueAsFloat = dict.Get<Float>("valueasfloat"_s))
			{
				ApplicationOutput("the element with name @ have the value @", name, value);
				continue;
			}
			
			ApplicationOutput("the element with name @ have the value @ and as float @", name, value, valueAsFloat);
		}
	}
	
	return maxon::OK;

}

Cheers,
Manuel

This post is deleted!

Hi kent,

we have this thread where you asked the question.

Following an example about how to read the data from a json like that. I've also add the case when you have the same keys in your json so you can loop over the elements.

There is no way of accessing directly a element in the json file.

#include "maxon/apibase.h"
#include "maxon/errorbase.h"
#include "maxon/errortypes.h"
#include "maxon/parser.h"
#include "maxon/application.h"

#include "c4d_general.h"


// This function read a json file and return the content as a datadictionary.
static maxon::Result<const maxon::DataDictionary> ReadJSONFile(const maxon::Url& jsonfFile)
{
	iferr_scope;
	CheckArgument(jsonfFile.IoDetect() != maxon::IODETECT::NONEXISTENT, "File doesn't exist"_s);
	
	// Create the parser for the json file and read it.
	maxon::BaseArray<maxon::DataDictionary> jsonArray;
	maxon::ParserRef parser = maxon::ParserClasses::JsonParser().Create() iferr_return;
	parser.Read(jsonfFile, maxon::PARSERFLAGS::NONE, maxon::GetUtf8DefaultDecoder(), jsonArray) iferr_return;
	if (jsonArray.IsPopulated())
		return jsonArray[0];

	return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Json file couldn't be read"_s);
}


static maxon::Result<void> pc13625(BaseDocument* doc)
{

	iferr_scope;
	/*
	 this function read the following json file:
	 
	 {
		 "a": [{
				 "b": "bbb",
				 "c": "ccc"
			 },
			 {
				 "d": "ddd",
				 "e": "eee"
			 }
		 ],


		 "b" : [{
			 "name" : "one",
			 "value" : 1
			 },
			 {
			 "name" : "two",
			 "value" : 2,
			 "valueasfloat" : 2.0
			 }
		 ]
	 }
	 
	 The element in the array "a" do not share the same keys. The first one have b and c, the second d and e. So we have to access all element one by one.
	 
	 In the array "b" the elements share the same keys so we can loop over them.
	 */
	
	
	
	const maxon::Url myJsonFile = maxon::Application::GetUrl(maxon::APPLICATION_URLTYPE::CURRENT_MODULE_DIR).Append("res"_s).Append("jsonexample.json"_s) iferr_return;

	
	const maxon::DataDictionary content = ReadJSONFile(myJsonFile) iferr_return;

	MAXON_SCOPE
	{
		// Reading array "a" we can't loop all the element because they have different keys.
		maxon::BaseArray<maxon::Data> arrayA = content.Get<maxon::BaseArray<maxon::Data>>("a"_s) iferr_return;
		const  maxon::Data& firstElement = arrayA[0];
		// we know the elements in the array are dictionary so we can convert Data to Dictionary
		maxon::DataDictionary bAndc = firstElement.Convert<maxon::DataDictionary>() iferr_return;
		const String b = bAndc.Get<String>("b"_s) iferr_return;
		const String c = bAndc.Get<String>("c"_s) iferr_return;
		
		const  maxon::Data& secondElement = arrayA[1];
		maxon::DataDictionary dAnde = secondElement.Convert<maxon::DataDictionary>() iferr_return;
		const String d = dAnde.Get<String>("d"_s) iferr_return;
		const String e = dAnde.Get<String>("e"_s) iferr_return;

		ApplicationOutput("value in the json are b:@ c:@ d:@ e:@", b, c, d, e);
	}
	
	MAXON_SCOPE
	{
		// reading array "B" we can loop over all elements because they share the same key.
		maxon::BaseArray<maxon::Data> arrayB = content.Get<maxon::BaseArray<maxon::Data>>("b"_s) iferr_return;
		for (maxon::Data& element : arrayB)
		{
			maxon::DataDictionary dict = element.Convert<maxon::DataDictionary>() iferr_return;
			const String name = dict.Get<String>("name"_s) iferr_return;
			const Int value = dict.Get<Int>("value"_s) iferr_return;
			
			// As the value as float is optionnal, we need a different path if the value doesn't exist.

			iferr (const Float valueAsFloat = dict.Get<Float>("valueasfloat"_s))
			{
				ApplicationOutput("the element with name @ have the value @", name, value);
				continue;
			}
			
			ApplicationOutput("the element with name @ have the value @ and as float @", name, value, valueAsFloat);
		}
	}
	
	return maxon::OK;

}

Cheers,
Manuel

Hi Manuel,

So sorry for the duplicate question. I did search yesterday for json and it didn’t pop up, but appears to show up now. Must have just missed it when searching.

My example above, as you pointed out, was supposed to be a consistent array of objects with the same parameters, so your answer using 'b' was what I was looking for. Again my bad on the confusing question.

But it is really great to see a full example, including all required headers, showing how to use this functionality.

I will give it a try next week. Again thanks for the going over this again.

Cheers,
Kent

Works great, thanks again Manuel.