Click here to Skip to main content
15,881,690 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I'm writing an article about a JSON reader I'm building, and I have these extractor structures that allow you to define paths to JSON values you want to pick out of the document. The reader can take these extractors and use them to populate your specified variables values from the document.

The extractors nest, meaning each one can potentially have children, which they take in the constructor. Because they take children in the constructor, you have to create the children first, and work from the leaves to the root.

A JsonElement is basically a variant type that can hold any kind of JSON value

A JsonExtractor structure represents one set of path segments or a value query. You can use one to
1. Navigate to one or more fields on an object
or
2. Navigate to one or more array elements in an array
or
3. extract the JsonElement value at the current position (could be string, boolean, number or null or undefined or array or object)

Whether it's type 1, 2 or 3 is determined by which constructor overload you called - did you give it a field list (#1), and indices list (#2), or a JsonElement pointer (#3)?

A query engine over this to abstract it would make it easier but I'm trying to avoid writing a query engine on top of it because this runs even on 8-bit with <8kB of ram and I want to keep it that way.

This creates an extractor that combs a JSON document for various elements, namely:
$.id
$.name
$.number_of_episodes
$.last_episode_to_air.name
$.created_by[0].name
$.created_by[0].profile_path

C++
// we want name and credit_id from the created_by array's objects
JsonElement creditName;
JsonElement creditProfilePath;
// we also want id, name, and 
// number_of_episodes_to_air 
// from the root object
JsonElement id;
JsonElement name;
JsonElement numberOfEpisodes;
// we want the last episode to air's name.
JsonElement lastEpisodeToAirName;

// create nested the extraction 
// query for $.created_by[0].name 
// and $.created_by[0].profile_path
const char* createdByFields[] = {"name","profile_path"};
JsonExtractor createdByExtractions[] = {
    JsonExtractor(&creditName),
    JsonExtractor(&creditProfilePath)
};
JsonExtractor createdByExtraction(createdByFields,2,createdByExtractions);

// we want the first index of the created_by array: $.created_by[0]
JsonExtractor createdByArrayExtractions[] = {
    createdByExtraction
};
size_t createdByArrayIndices[] = {0};
JsonExtractor createdByArrayExtraction(
    createdByArrayIndices,
    1,
    createdByArrayExtractions
  );

// we want the name off of last_episode_to_air, like $.last_episode_to_air.name
const char* lastEpisodeFields[] = {"name"};
JsonExtractor lastEpisodeExtractions[] = {
    JsonExtractor(&lastEpisodeToAirName)
};
JsonExtractor lastEpisodeExtraction(
    lastEpisodeFields,
    1,
    lastEpisodeExtractions
  );

// we want id,name, and created by from the root
// $.id, $.name, $.created_by, 
// $.number_of_episodes and $.last_episode_to_air
const char* showFields[] = { 
    "id",
    "name",
    "created_by",
    "number_of_episodes",
    "last_episode_to_air"
};
JsonExtractor showExtractions[] = {
    JsonExtractor(&id),
    JsonExtractor(&name),
    createdByArrayExtraction,
    JsonExtractor(&numberOfEpisodes),
    lastEpisodeExtraction
};
JsonExtractor showExtraction(showFields,5,showExtractions);

I don't like doing nested structures in C and C++ generally because it creates code like this, but sometimes it feels like the best way given the situation.

my question is, given I'm writing an article that explains it, how ugly is this really? Is this code something a decent developer can understand if they study it a bit or do you think I only understand it because I wrote it?

Do you have any ideas to restructure it maybe if it can be done without adding a ton of extra code/abstractions (this is a close-to-the-metal API and library)

What I have tried:

I've tried the code in the above. This section doesn't really apply to me question, sorry.
Posted
Updated 22-Dec-20 3:39am
v4
Comments
[no name] 22-Dec-20 10:01am    
4 versions within 13 minutes ... :o)

Some people understand words better; other need pictures (object graphs). Targeting a wide audience then requires both. (Not "both" ... the picture will usually trump text).
honey the codewitch 22-Dec-20 10:03am    
I know i know. it's early and i'm sleepy and typos and poorly worded thoughts flow freely from me right now.

Edit: (per yours), Yeah I may need to break out paint!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900