Problems selecting JSON Object

Hey there.

Currently trying my hands on a WS Script for fanart.tv. So far I've been able to get the data from the API to load (yay), but I'm not sure if I'm doing it right. There is no output when I use json_object, so I don't know if it accessed it, since it also doesn't error out when it doesn't find an object by that name.

But first, here's the current code:

# ###################################################################
# Mp3tag Tag Source for FanartTV API
#
# Search by MusicBrainz Release-Group ID
#
# This file should be stored in your tag sources sources directory
# %APPDATA%\Mp3tag\data\sources
# and requires Mp3tag v2.64 or above.
#
# ###################################################################

[Name]=Fanart.tv
[BasedOn]=www.fanart.tv
# Append personal API Key, more info about them here:
# <a href="https://fanart.tv/2015/01/personal-api-keys/" target="_blank">https://fanart.tv/2015/01/personal-api-keys/</a>
[IndexUrl]=http://webservice.fanart.tv/v3/music/albums/%s?api_key=738e7602362418fda8158f44fb12e6df&client_key=
[IndexFormat]=%_url%|%preview%
[SearchBy]=%MUSICBRAINZ RELEASE GROUP ID%

[ParserScriptIndex]=...
# ###################################################################
#					I  N  D  E  X
# ###################################################################
debug "on" "C:\Users\Tarulia\AppData\Roaming\Mp3tag\debug_fanarttv.txt" "5"

json "ON"

# API returns 404 on error, no need to read out error message as Mp3tag errors out on 404

# get the actual image
json_select_object "albums"
    json_select_object "8f4d4f05-36ed-3c81-86a7-aae2a03b1520"
        json_select_array "albumcover" 0
            json_select "url"
                outputto "coverurl"
                sayrest

And the Debug Output (note that I commented out the select_array and following, see below)

Total output to process:
------------------------------------------------------------
{
    "name": "3 Doors Down",
    "mbid_id": "2386cd66-e923-4e8e-bf14-2eebe2e9b973",
    "albums": {
        "8f4d4f05-36ed-3c81-86a7-aae2a03b1520": {
            "cdart": [
                {
                    "id": "8618",
                    "url": "http://assets.fanart.tv/fanart/music/2386cd66-e923-4e8e-bf14-2eebe2e9b973/cdart/away-from-the-sun-4e484652567b2.png",
                    "likes": "2",
                    "disc": "1",
                    "size": "1000"
                },
                {
                    "id": "61074",
                    "url": "http://assets.fanart.tv/fanart/music/2386cd66-e923-4e8e-bf14-2eebe2e9b973/cdart/away-from-the-sun-509e55644d26d.png",
                    "likes": "0",
                    "disc": "1",
                    "size": "1000"
                }
            ],
            "albumcover": [
                {
                    "id": "190047",
                    "url": "http://assets.fanart.tv/fanart/music/2386cd66-e923-4e8e-bf14-2eebe2e9b973/albumcover/away-from-the-sun-56cc1174dfda4.jpg",
                    "likes": "2"
                }
            ]
        }
    }
}
------------------------------------------------------------


Output         : ><

Line and position:
{
^

------------------------------------------------------------

Script-Line    : 26
Command        : json
Parameter 1    : >ON<

Output         : ><

Line and position:
{
^

------------------------------------------------------------

Script-Line    : 31
Command        : json_select_object
Parameter 1    : >albums<

Output         : ><

Line and position:

^

------------------------------------------------------------

Script-Line    : 32
Command        : json_select_object
Parameter 1    : >8f4d4f05-36ed-3c81-86a7-aae2a03b1520<

Output         : ><

Line and position:

^

------------------------------------------------------------

Total output:
 output["CurrentUrl"]= "http://webservice.fanart.tv/v3/music/albums/8f4d4f05-36ed-3c81-86a7-aae2a03b1520?api_key=738e7602362418fda8158f44fb12e6df&client_key="
 output["Output"]= ""
 output["Error"]= "<OK>"

Note that I hardcoded the second json_select_object for testing.

Now I have multiple problems:

1. When I use ParserScriptAlbum instead of ParserScriptIndex, no log file is created. At all. Also I have no idea what's the difference really, but I assume I actually need the ParserScriptAlbum since it's probably showing the result of the selected album?

2. When I use the script like that, there is no log file created, at all, unless I comment out the json_select_array and the following lines.

3. In the real world I can't actually hardcode the MBID into the json_select_object function, but I haven't been able to use the actual ID in any way. I tried using %MUSICBRAINZ RELEASE GROUP ID% and %s both with and without quotes, but according to the debug output the value isn't used. Is there even a way of using that variable? If not, well.. I got a problem :slight_smile: Can I use json_foreach on the albums object or does it not work on objects, but only on arrays?

4. Is it normal that there is no Output when selecting an object? I have no idea if the selection actually works or not. Is there a way to get a serialized version of the selected object into the output?

Hope someone can give me a hint and/or get me on the right track from where I can continue on my own :slight_smile:

Thanks in advance

/bump

Any ideas on this? :slight_smile:

If all else fails I'll probably just go ahead and re-write the whole thing using the usual parsing functions, but I'd like to do it the "right" way (when we already have JSON functions, why not use it huh? :slight_smile: )

/Edit:

Solved this one... It was a little late I guess :slight_smile: Parsing the IndexUrl won't work with the ParserScriptAlbum I guess :slight_smile:

/Edit #2

Well... yeah... solved that one too. Must be the only scripting language where the first element of an array is actually 1 and not 0 :stuck_out_tongue:

Currently I have this then:

json "ON"
outputto "coverurl"
json_select_object "albums"
    json_select_object "8f4d4f05-36ed-3c81-86a7-aae2a03b1520"
        json_select_array "albumcover" 1
            json_select "url"
                sayrest

Problem is, there's nothing in the debug output that really helps me. Selecting anything doesn't give any hint of what it selected, or if it even selected in the first place. It doesn't even tell me when it couldn't find the object we're looking for (for example searching for "alsfsdfbusodfudshms" doesn't return an error, it just does nothing).

/Edit 3
Using json_foreach "albumcover" works but I don't really get why... I don't see why iterating over "every" (in this case 1) array-element would work, but using array element 1 directly wouldn't...

Problem is there are a few cases where there are multiple images. I want to build an Index at some point, but that's another project for another day. I just want to make it work for now :slight_smile:

/Edit 4
As a sidenote, as I was playing around without using the JSON functions I tried joinLines until the end of the input, but using an arbitrary large number doesn't work, leaving the argument empty doesn't work either, and there doesn't seem to be a way of getting the number of lines in the input. Is there even a way to do that?

PS: When there's a stray json_foreach_end it appears Mp3tag just crashes (I had it when I had the json_foreach and tried json_select_array again but forgot to comment out the json_foreach_end)

2 Likes

Hi @Mihawk90, I noticed the same.
It works well if the number does NOT exeed the exact number of lines in the input stream.
Tried
JoinLines 0
JoinLines -1
JoinLines 10000
No success.
To me it looks a bug.
Only @Florian could give the most competent answer. :crossed_fingers:

It's not clear to me on what you're referring to. If you thing you found a bug, please provide a minimal example exemplifying the issue and that allows for reproducing the issue.

Since the original post is 4 years old at this point I don't remember what exactly the issue was or even if the original issue is still relevant anymore.

Back then I "solved" this by just parsing the returned JSON result using the regex parser that is also used for websites and that worked well enough for the usecase. I have not worked on any webscript since then so I cannot comment on whether this is still an issue.

1 Like

Thanks for the quick reply. My question was also more directed to @vkostas since he resurrected the topic from the archives.

1 Like

What I was wanting to say with that is that I also don't know if this is even the same issue. But I guess that @vkostas was referring to this:

I think I was trying to join the entire API response into one line for easier RegEx parsing for what I actually wanted to get to. But in doing this I encountered the issue that this was not easily possible as I didn't know the response length beforehand, and there didn't seem to be a way to get this information either.

I don't think it is strictly speaking a bug, more like a limitation of the JoinLines function.

VGMdb Search by &Album JSON Normalize_BUG.src (921 Bytes)
Input stream has exactly 357 lines
Any attempt to join more than 357 lines would fail the script
JoinLines 357 <<<< It works
JoinLines 358 <<<< FAILURE !!!!! with error "Sorry, No entries are matching your search criteria."

Thank you @Florian for having a look at the attached example.
PS: Above is required to apply some modifications to the input stream. Finally the "modified" JSON will be parsed after initiating JSON "on" "current" command.

Amended and simplified script (VGMdb does not connect with previous script).
VGMdb Search by &Album JSON Normalize_BUG.src (549 Bytes)

Thanks for the example scripts — very helpful to reproduce what you mean.

Do you have a preference on how JoinLines should behave when the parameter exceeds the available lines number?

Also, I was thinking about a JoinAll function that joins everything from the current position to the end to make the intention a little bit more clearer.

Personally I think it should just go to the specified lines or the end of the input, whichever comes first.

I'm not sure what the original intent with JoinLines was since most APIs will have a varying response length anyway (and datafields also may vary in position in the response since it often doesn't matter), so there is no way to tell beforehand how many lines will need to be joined. Maybe it could also log whether it hit the end of input or the specified number.

Hey Florian,
JoinAll would cover 99.99% of the cases. I don't expect anyone would like to join arbitrary number lines.
The same could be achieved by JoinLines "-1" or JoinLines "0". It is really a matter of taste.
I have no specific preference, whatever it is easier for you.
Thanks again.

With Mp3tag v3.04b, JoinLines now uses all available lines if parameter is -1 or exceeds the input range.

1 Like

Tried and works. Thank you Florian.

1 Like