Suggestion: Implementation of missing json functions to inquire json object names

The deezer web source uses for artist names and their roles a json object that looks like that:

{"SNG_CONTRIBUTORS":{"composer":["Riley B. King","Jules Bihari"],"main_artist":["Eric Clapton","B.B. King"],"music publisher":["Power Force Music (BMI)","Careers-BMG Music Publishing, Inc. (BMI)"]}}

I wanted to extract these json data and write it into the tag field INVOLVEDPEOPLE, that has the very similar structure:

Role1:Person1;Role2:Person2;

I hoped that it would be possible with the available json functions to get to

Composer: Riley B. King, Jules Bihari; Main_Artist: Eric Clapton, B.B. King;...

Sadly, I could not find a json-based solution to extract the array names composer, main_artist, music publisher and all the other possible roles. This means that I would have to know in advance, which roles can appear in the object and I would have to write a dedicated script part for every one of them. This is impossible. Instead I would favor a dynamic solution that delivers the names of the available json objects and this way makes it easy to read the named json arrays.

The following new json functions probably could fill this gap:

  • a loop to iterate through the json objects: This function could be called json_foreach_object in analogy to json_foreach, that iterates through a json array;
  • a function to read the name of the current object: json_select_name or json_foreach_name in analogy to json_foreach_counter.

With these new json functions my script now could simply be:

json_select_object "SNG_CONTRIBUTORS"
	json_foreach_object
		set "Role"
		outputto "Role"
		json_select_name
		sayrest	
		json_select_array "%Role%" -1 ", "
		outputto "INVOLVEDPEOPLE"
		sayoutput "Role"
		say ": "
		sayrest 
		say ";"
	json_foreach_end
json_unselect_object

I should mention that I actually use a workaround for this issue, that extracts the names of the arrays with a regular expression before the json mode is switched on, and that uses a do while loop to finally build the tag INVOLVEDPEOPLE

Thanks for the suggestion. I checked the current implementation and agree that there is currently no way to iterate over JSON object member names dynamically.

One detail I would like to confirm: if a future json_foreach_object follows the existing behavior of json_foreach, the current JSON item inside the loop would become the current member value. In your example, that means the current item would already be the array for the current role, e.g., ["Riley B. King","Jules Bihari"].

In that case, the array selection would probably need to use an empty selector:

json_select_array "" -1 ", "

instead of the %Role% selector from your example:

json_select_array "%Role%" -1 ", "

The latter would only work if json_foreach_object kept the current JSON item at the parent object and only exposed the current key separately.

Would the behavior that's consistent with json_foreach work for your use case, where the loop exposes the current object name via, e.g., json_foreach_name and the current item is the corresponding value?

Yes I think that would work for me too. It looks even to be simpler. And it seems that, alternatively to my original suggestion, json_foreach could be extended to be used for both cases: arrays and objects, instead of intruducing an new command json_foreach_object. That's because the functionality would be the same and only the objects differ.
Similar the function of json_foreach_counter could be extended to deliver the objects name (or key) in case the loop iterates over objects. A separate new command json_select_name or json_foreach_name would then not be necessary.
So finally with these proposed extension of the existing commands my code example would be 4 lines shorter:

json_select_object "SNG_CONTRIBUTORS"
	outputto "INVOLVEDPEOPLE"
	json_foreach
		json_foreach_counter
		say ": "
		json_select_array "" -1 ", "
		sayrest 
		say ";"
	json_foreach_end
json_unselect_object

This alternative has one more benefit: No new commands, that could confuse the programmers, are introduced, only the documentation of existing commends needs to be changed. :wink: except, of course, the implementation effort for the developer @Florian !

Thank you for the suggestion! I spent the day working on this and extended json_foreach with support for iterating JSON objects and outputting object keys via json_foreach_counter.

This is now possible with Mp3tag v3.36-beta.3.

Thank you very much for your work, @Florian ! I have tried and it works perfectly. Your implementation is even better than I imagined, because my example script now actually does not need to select the json object before the loop any more, instead it can simply name it with the json_foreach command:

	outputto "INVOLVEDPEOPLE"
	json_foreach "SNG_CONTRIBUTORS"
		json_foreach_counter
		say ": "
		json_select_array "" -1 ", "
		sayrest 
		say ";"
	json_foreach_end