Command to Look Up specific Line in JSON based on Query

Hi! I’m trying to make a command that takes a query from the user, and uses it to search an array, and print the line identified with the query. Specifically, I want a “Pokedex”, where the query would be the name of a pokemon, and the result would be the line from my JSON about that pokemon.

I currently have this command, which I got from this thread:

$(eval a=$(urlfetch json https://gist.githubusercontent.com/webcamcals/8daa9da5679173ad7c915a86231a7d99/raw/67fc6d499638614df14d857ee079af7ebed5f3cb/pokedex3.json);a[parseInt(decodeURIComponent(`$(querystring)`))-1]||a[Math.floor(Math.random()*a.length)])

This works using numbers (eg !dex 1 prints the first line, which contains information for Pokemon #1, Bulbasaur, etc). And with no input from the user after the command, it outputs a random line. That’s pretty good! But ideally, it would function using Pokemon names as input (ignoring case), eg !dex bulbasaur would return line number 001, containing information about Bulbasaur.

The JSON I’m working with was exported out of a spreadsheet and edited in Notepad++, so I am able to format it differently, which might help if it’s necessary to do something else to demarcate specifically where the pokemon’s name is in the line; I think that some pokedex entries contain the names of other pokemon, which could complicate searching the whole document, unless it’s possible to identify names that are in their own column / bounded by separator characters, as they are here.

Or, if it’s possible to do two lookups with one command, pokemon names could be converted to numbers using a different, simpler list containing only names, and then the line number containing a match for the query could be pulled from the full json, as they are currently.

Any help with this would be massively appreciated!

Hey @webcamkcals!

I’m surprised your command works in the first place given it’s not properly formatted JSON, but I’m happy for you it does.

Now, to address your issue, the best solution is in my opinion to switch the array to an object:

["001 | Bulbasaur | Seed Pokémon | 𝗚𝗿𝗮𝘀𝘀🍃 / 𝗣𝗼𝗶𝘀𝗼𝗻🧪 | 2'04\" | 15.2 lbs | BMI 14.1 (Underweight) | Since the day it was born there is a strange bulb planted on its back containing numerous seeds and nutrients. The bulb itself stores energy and the nutrients it needs to grow and with the help of the sun it can go days without eating because it use",
"002 | Ivysaur | Seed Pokémon | 𝗚𝗿𝗮𝘀𝘀🍃 / 𝗣𝗼𝗶𝘀𝗼𝗻🧪 | 3'03\" | 28.7 lbs | BMI 13 (Underweight) | When its exposed to sunlight the bulb now a bud grows so much that it can apparently lose the ability to stand on its hind legs and adds to its strength. To support this weight its legs have grown thicker and stronger and it grows by drawing in energy. T",
"003 | Venusaur | Seed Pokémon | 𝗚𝗿𝗮𝘀𝘀🍃 / 𝗣𝗼𝗶𝘀𝗼𝗻🧪 | 6'07\" | 220.5 lbs | BMI 25 (Healthy) | It's always on the move to seek sunlight so it can absorb it for energy and when it does this it tends to lay still. The aroma from the flower it now has on its back can sooth the emotions of people. It's said that if a Venusaur gets enough sunlight and nu",
// ...
]

From above (note that I reformatted the JSON) to below.

{"bulbasaur": "001 | Bulbasaur | Seed Pokémon | 𝗚𝗿𝗮𝘀𝘀🍃 / 𝗣𝗼𝗶𝘀𝗼𝗻🧪 | 2'04\" | 15.2 lbs | BMI 14.1 (Underweight) | Since the day it was born there is a strange bulb planted on its back containing numerous seeds and nutrients. The bulb itself stores energy and the nutrients it needs to grow and with the help of the sun it can go days without eating because it use",
"ivysaur": "002 | Ivysaur | Seed Pokémon | 𝗚𝗿𝗮𝘀𝘀🍃 / 𝗣𝗼𝗶𝘀𝗼𝗻🧪 | 3'03\" | 28.7 lbs | BMI 13 (Underweight) | When its exposed to sunlight the bulb now a bud grows so much that it can apparently lose the ability to stand on its hind legs and adds to its strength. To support this weight its legs have grown thicker and stronger and it grows by drawing in energy. T",
"venusaur": "003 | Venusaur | Seed Pokémon | 𝗚𝗿𝗮𝘀𝘀🍃 / 𝗣𝗼𝗶𝘀𝗼𝗻🧪 | 6'07\" | 220.5 lbs | BMI 25 (Healthy) | It's always on the move to seek sunlight so it can absorb it for energy and when it does this it tends to lay still. The aroma from the flower it now has on its back can sooth the emotions of people. It's said that if a Venusaur gets enough sunlight and nu",
// ...
}

And so, your command needs to be updated as such:

$(eval const data = $(urlfetch json LINK_TO_JSON_DATA); const dataArray = Object.values(data); const query = '$(query)'.toLowerCase(); query === '' ? dataArray[Math.floor(Math.random() * dataArray.length)] : isNaN(parseInt(query)) ? data[query] : dataArray[parseInt(query) - 1];)

I recommend you switch to a raw Pastebin (create an account) to save characters, and the keys for each entries of your object should be lowercase.
And note that there are no error handling, so if someone were to enter the name of a Pokémon that doesn’t exist, or makes a typo, the bot will responds with a generic error.

1 Like

i would give this a try… bit crude by comparison, lol, but i think it’ll do the trick…

$(eval a=$(urlfetch json https://gist.githubusercontent.com/webcamcals/8daa9da5679173ad7c915a86231a7d99/raw/67fc6d499638614df14d857ee079af7ebed5f3cb/pokedex3.json);b=`$(query)`.toLowerCase();b==b*1?a[parseInt(decodeURIComponent(`$(querystring)`))-1]:b==``?a[Math.floor(Math.random()*a.length)]:a[a.findIndex((c.toLowerCase().includes(b))(c))])

edit: lol, oops… @Emily types faster than i do XD … her fix is better than mine, not sure mine will even work, or fit in the command response field, lol

2nd edit: yeah, i totally skipped the .toLowerCase() part that i had intended to put in there when i started XD … if i knew how to delete my response i would XD

now i added it, lol :stuck_out_tongue:

2 Likes

Haha, I was just browsing earlier than you and therefore started solving this one sooner.

I like your solution tho’, gives something to think about… (please don’t delete it, but if you need to in the future, the option is under the 3 dots next to the Reply button)
I think I would have preferred yours if this wasn’t an issue:

I’m not entirely sure this would work:
a[a.findIndex((c.includes(b))(c))]
But this would for sure:
a[a.findIndex(c => c.includes(b))]

1 Like

I just noticed, the responses in your array seem to be cut short? I don’t know if it’s intentional, but just in case, Nightbot will allow you to send a response up to 400 characters on Twitch, and 200 on YouTube.

Hi! I just saw this thread was approved, and I still have to take some time trying out your suggestions, which I appreciate!! But this one is quick to answer; I got more than half of the pokedex entries from a spreadsheet some other guy made, and those ones were poorly-written, and had spelling errors, and some editorializing, i think. But I would rather use =importhtml to bring them into my spreadsheet (and hopefully laugh at the weird errors) than manually paste all 1025 pokedex entries myself, so I went with that. I used notepad++ to truncate the lengths, and I think i went down to like 360 characters or so per line, to accommodate the fancy ascii text I wanted to have in there (and I wasn’t sure how many characters that counted as lol). I didn’t want them to be too long, anyway, so I was okay with truncating them.

Ok now I’m going to read the responses and try stuff out!!

1 Like

Unfortunately I don’t think I can use Pastebin for this; I have an account, but Pastebin has a “feature” that automatically detects “potentially offensive” content, and my pokedex was setting it off for some reason (:woman_shrugging:). I guess some of the entries talk about death, or something? I really have no idea there lol.

When I was still trying to use pastebin for this, I saw some stuff about how you can add a “?i=”, and then your API key, to the end of your url, to access private pastes through the API. But I couldn’t get it to work; I was getting “Unexpected identifier ‘Server’ [:1:10]”. That’s why I switched to github, which I had never used before :frowning: I would have preferred to use pastebin!

I definitely have to fix this array, too. Disclaimer that I have no idea what im doing, have never used a json before, and was completely just going off of this post in the thread I linked in the OP. :sweat: Gonna keep reading and try to fix it

1 Like

Probably-dumb question about punctuation: I see @Emily used backslashes to distinguish quotation marks that mean “inches” from the quote marks designating , um, whatever you call ‘sections’ of the ‘object’, or whatever. Sorry. I have no idea what I’m talking about.

Anyway, as I’m editing this file in Notepad++, trying to get the formatting fixed, I notice that it’s highlighting certain quotation marks inside of the pokedex entries.


That makes sense to me, and it looks like it there aren’t too many of them to make it intimidating to manually add a backslash in front of each quote mark myself (I’d be hesitant to do a big search-and-replace, and probably mess up some other needed quotation marks elsewhere).

What I do find interesting, though, is how it doesnt seem to have an issue with the quotation marks listed in the height category? Obviously, this is just notepad++, which is totally separate from nightbot, which is actually going to be using it. I could also pretty easily batch-replace all of those quotation marks without issue, because they always have a space and a separator character after them. I guess I should be safe, and put backslashes in front of those too, probably?

Edit:
I tried batch-replacing the “inches” quotation marks with ’ " ', and it really didn’t like that! :sweat:

Edit 2:
I went ahead and tried the suggested code with what I’ve got so far, which I may well have messed up on.
So this:
$(eval const data = $(urlfetch json https://gist.githubusercontent.com/webcamcals/270e66a9342158482e67f0efd2c7e4cf/raw/3632520b0cd0d9bc828e2477eba636962b19fa7f/pokedexqq.json); const dataArray = Object.values(data); const query = '$(query)'.toLowerCase(); query === '' ? dataArray[Math.floor(Math.random() * dataArray.length)] : isNaN(parseInt(query)) ? data[query] : dataArray[parseInt(query) - 1];)
(this is the version with the “inches” quotation marks preceded with a backslash, which I tried second)

When I didn’t have backslashes in front of the “inch” quotes, i got Unexpected token ':' [<context>:1:65709], and when I did, I got Unexpected token ':' [<context>:1:65908] It looks to my very-uneducated eyes that something is amiss with the colon!!!

lol, so the backslashes used in this way r called “escape characters” which tell it not to end the string (the data type that contains words) and if u haven’t finished converting those, that’s probably what it did… that or if u added a colon after the data… if u’ve already changed all that i wouldn’t undo it now, but u can avoid using escape characters if u use backticks instead of quotes… like this…

a = "Jerry's \"farm\" sucks!"
b = 'Jerry\'s "farm" sucks!'
c = `Jerry's "farm" sucks!`

all 3 of these will put the exact same thing on the screen, but i favor backticks so u don’t need any escape characters… so far in all my code it works everywhere except as keys in an object (in Emily’s message the new version of your list has black and red words… the black r the keys and the red r the values, keys still need quotes, but the values can use backticks)…
but anyway, my best guesses for the colon error would be if u added a colon after a value OR if u missed a comma… objects need commas between attributes too… like this…

{ "key1": `value1`,
"key2": `value2`,
"key3": `value3` }

(not sure which formatting Emily used to get the different colors)

2 Likes

Yeah… all the questions you have are answered in the link to the JSON specifications in my first answer, but basically when you want to put double quotes " in a string that’s defined by double quotes itself, you need to escape the double quotes that are inside the string, by using a backslash: \".

The height section was fine is because it used another format of the double quotes: , but I thought it’d be better to use the good version of quotes everywhere, I think the reason why it turned to red once you added the backslash in the height section is because you kept using the wrong double quote, JSON doesn’t recognize escaping that quote character.
Note the difference between " and ; and ' and (Notepad++ shows the difference too), it’s very subtle, but it’s a big deal. Apart from the use of the wrong quotes in the height section, I don’t see anything else that could be breaking your code, so I simply suggest replacing those with " ' respectively, and your command should work. Unless are the good quotes for height? I don’t know, I use the metric system, in which case simply remove the backslash you added last time: \” back to .

That’s also why I encouraged to use double quotes, as it’s the JSON format, because I think it’s a good habit to use the correct syntax, it reduces the risk of issues down the line, but as @tiwosslave pointed out, other type of quotes should work too for the values, Nightbot must be parsing the data.


PS (for @tiwosslave :wink:): I used the JSON formatting to get those colors:

```json
{
  "key": "value",
  "key": "value"
}
```
{
  "key": "value",
  "key": "value"
}
1 Like

oh man… I had backticks in my original version, but i changed it to quotes as suggested. I could probably switch back using a couple of search-and-replaces, or going back to an older version of my file, but I think i’m going to keep rolling with the quotes because I’m (hopefully?) close to having it working haha

Okay, I definitely did not note that!! Oops. Thankfully, I have been making multiple copies of my file when I change things, so I’m going back with the previous version, which uses ” for inches.

So, I think the real problem is just ":"s, as Nightbot indicated! I’m going to continue experimenting a little bit, and I’m focused on two things:

  1. Colons in the values, as pointed out by @tiwosslave. I had Notepad++ mark all the “:” in the document, and there are indeed one or two colons inside of pokedex entries. I’ll have to see if i can use escape characters on those (:pleading_face:), or if I just have to delete them or replace them with some other punctuation.
  2. Colons in the keys: There is one of these. Unfortunately, there is a pokemon with a colon in its name, and he’s already caused me some issues before, when I made a similar thing using python and Streamer.bot (but that only works on twitch while my computer is on, which is why I’m interested in having a nightbot-based solution). So I’ve got a bit of a grudge against this guy, not gonna lie…

    Can I have a colon in the key? With or without an escape character?

I was going to wait to bring it up if/when I had this working at all, but maybe I might as well bring it up here: What would be the preferred way to have multiple keys with the same value, to allow for differences in spelling/symbol usage? When I was making the other Streamer.Bot-based thing I was talking about above, I kept a short list of “Problem Pokemon” with weird characters in their names. Like, there’s “Mr. Mime”, with a period, “Flabébé”, with the accented "e"s, “Porygon-Z” with a hyphen, and “Nidoran♀” with the female symbol. Ideally, I would allow for a few possible spellings for these, like, “mr mime”, “flabebe”, “nidoran female”, and so on. Is it possible to have multiple keys listed on the same line , associated with the same value? Or is the proper way to just duplicate the whole line and change the key? I’m irrationally scared of doing the latter option, because it seems beneficial to preserve the current format of every line of the document matching the pokedex number of the pokemon on that line. Maybe that’s not an option, though. Anyway this whole paragraph is not urgent, but it’s something I would be interested in learning more about, especially if I can make this work in the first place :slight_smile:

the colons in the values r fine as long as they’re within the string… but for the key question, only one key per value… the only way to get multiple things on the “same line” would be for that value to be an array, but, it would still only have a single key and wouldn’t work well with this formatting…

2 Likes

Oh my god, it’s working!! It turns out that ol’ Type: Null was actually innocent, here. The culprit was none other than SLOWKING!
slowking
Looks innocent enough, doesn’t he? Well, admittedly, he is. But that guy who tried to synthesize every Pokedex entry into one big one had a sentence with lots of quotes and a colon in it, which I apparently messed with when I was mass-reformatting my document using Notepad++ search-and-replace, which made this line look like it was another key/value pair at the end here:


I simply replaced that whole entry with a simpler, actual pokedex entry from the pokemon wiki, and it’s all working now!!! Thanks so much for your help @Emily and @tiwosslave ; you’ve been right from the very beginning, and I just had to get my formatting right! And now I feel empowered to make similar lookup commands in the future, if the need arises! So grateful for your effort in educating + helping me thx!! :yellow_heart::yellow_heart::yellow_heart:

2 Likes

That’s awesome to hear, have fun making commands, and we’re always here if you need help!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.