Accesing Json data after 'loading' it - json

With a lot of help from people in this site, I managed to get some Json data from an amazon page. The data, for example, looks like this.
https://jsoneditoronline.org/?id=9ea92643044f4ac88bcc3e76d98425fc
First I have a list of strings which is converted to a string.
script = response.xpath('//script/text()').extract()
#For example, I need the variationValues data
variationValues = re.findall(r'variationValues\" : ({.*?})', ' '.join(script))[0]
Then, in my code, I have this (not a great name, will be changed later)
variationValuesJson = json.loads(variationValues)
variationValuesJson is in fact a dictionary, so doing something like this
variationValues["size_name"][3]
Should return "5.5 M US"
My issue is that, when running the program, I get the string indices must be integers error. Anyone knows whats wrong?
Note: I have tried using 'size_name' instead of "size_name", same error

variationValues["size_name"][3] #this is the raw string which you have converted to variationValuesjson
I think this is not what you actually want.
Your code should be this.
variationValuesJson['size_name'][3] #use variationValuesjson ;)

Related

JSON error with Julia Dash simple example

I've been trying to replicate the "A simple example" posted at https://dash-julia.plotly.com/clientside-callbacks
The server runs... but when I connect to it I get a JSON parse error in Firefox.
I was able to solve the problem, but I'd like to understand what's wrong...
The problem was this line inside the Dash app.layout:
options=[(label = country, value = country) for country in available_countries]
and the available_countries variable was obatined from:
read_remote_csv(url) = DataFrame(CSV.File(HTTP.get(url).body))
df = read_remote_csv("https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv")
available_countries = unique(df.country)
Apparently the error showed because available_countries was an Array{String31,1}: and specifically the problem was the String31 type.
when I converted the variable to a plain String type:
available_countries = convert(Array{String,1},available_countries)
the problem solved.
Now... I'm not sure if the String31 type came from the HTTP.get(), CSV.File() or the DataFrame() functions.
I'm assuming the example used to work when it was originally written but it broke with an update...
Can anyone explain where exactly the error originates? Is it a Package version thing? which package? (HTTP, CSV, Dataframes)? How can I avoid it moving on?

Deserialize JSON without knowing full structure

I'm redoing the backend of a very basic framework that connects to a completely customizable frontend. It was originally in PHP but for the refactor have been plodding away in F#. Although it seems like PHP might be the more suited language. But people keep telling me you can do everything in F# and I like the syntax and need to learn and this seemingly simple project has me stumped when it comes to JSON. This is a further fleshed out version of my question yesterday, but it got alot more complex than I thought.
Here goes.
The frontend is basically a collection of HTML files, which are simply loaded in PHP and preg_replace() is used to replace things like [var: varName] or [var: array|key] or the troublesome one: [lang: hello]. That needs to be replaced by a variable defined in a translation dictionary, which is stored as JSON which is also editable by a non-programmer.
I can't change the frontend or the JSON files, and both are designed to be edited by non-programmers so it is very likely that there will be errors, calls to language variables that don't exist etc.
So we might have 2 json files, english.json and french.json
english.json contains:
{
"hello":"Hello",
"bye":"Goodbye"
}
french.json:
{
"hello": "Bonjour",
"duck": "Canard"
//Plus users can add whatever else they want here and expect to be able to use it in a template
}
There is a template that contains
<b>[lang: hello]</b>
<span>Favourite Animal: [lang:duck]</span>
In this case, if the language is set to "english" and english.json is being loaded, that should read:
<b>Hello</b>
<span>Favourite Animal: </span>
Or in French:
<b>Bonjour</b>
<span>Favourite Animal: Canard</span>
We can assume that the json format key: value is always string:string but ideally I'd like to handle string: 'T as well but that might be beyond the scope of this question.
So I need to convert a JSON file (called by dynamic name, which gave F# Data a bit of an issue I couldn't solve last night as it only allowed a static filename as a sample, and since these two files have potential to be different from sample and provided, the type provider doesn't work) to a dictionary or some other collection.
Now inside the template parsing function I need to replace [lang: hello] with something like
let key = "duck"
(*Magic function to convert JSON to usable collection*)
let languageString = convertedJSONCollection.[key] (*And obviously check if containsKey first*)
Which means I need to call the key dynamically, and I couldn't figure out how to do that with the type that FSharp.Data provided.
I have played around with some Thoth as well to some promising results that ended up going nowhere. I avoided JSON.NET because I thought it was paid, but just realised I am mistaken there so might be an avenue to explore
For comparison, the PHP function looks something like this:
function loadLanguage($lang='english){
$json = file_get_contents("$lang.json");
return json_decode($json, true);
}
$key = 'duck';
$langVars = loadLanguage();
$duck = $langVars[$key] || "";
Is there a clean way to do this in F#/.NET? JSON seems really painful to work with in comparison to PHP/Javascript and I'm starting to lose my mind. Am I going to have to write my own parser (which means probably going back to PHP)?
Cheers to all you F# geniuses who know the answer :p
open Thoth.Json.Net
let deserialiseDictionary (s: string) =
s
|> Decode.unsafeFromString (Decode.keyValuePairs Decode.string)
|> Map.ofList
let printDictionary json =
json
|> deserialiseDictionary
|> fun m -> printfn "%s" m.["hello"] // Hello
For the question about 'T the question becomes, what can 'T be? For json it very limited, it can be a number of things, string, json-object, number, bool or json array. What should happen if it is bool or a number?

interpreting a json string

I have an object in my database following a file upload that look like this
a:1:{s:4:"file";a:3:{s:7:"success";b:1;s:8:"file_url";a:2:{i:0;s:75:"http://landlordsplaces.com/wp-content/uploads/2021/01/23192643-threepersons.jpg";i:1;s:103:"http://landlordsplaces.com/wp-content/uploads/2021/01/364223-two-female-stick-figures.jpg";}s:9:"file_path";a:2:{i:0;s:93:"/var/www/vhosts/landlordsplaces.com/httpdocs/wp-content/uploads/2021/01/23192643-threepersons.jpg";i:1;s:121:"/var/www/vhosts/landlordsangel.com/httpdocs/wp-content/uploads/2021/01/364223-two-female-stick-figures.jpg";}}}
I am trying with no success to parse extract the two jpg urls programmatically from the object so i can show the images ont he site. Tried assigning parse(object) but that isnt helping. I just need to get the urls out.
Thank you in anticipation of any general direction
What you're looking at is not a JSON string. It is a serialized PHP object. If this database entry was created by Forminator, you should use the Forminator API to retrieve the needed form entry. The aforementioned link points to the get_entry method, which I suspect is what you're looking for (I have never used Forminator), but in any case, you should look for a method that will return that database entry as a PHP object containing your needed URLs.
In case it is ever of any help to anyone the answer to the question was based on John input. The API has the classes to handle that without needing to understand the data structure.
Forminator_API::initialize();
$form_id = 1449; // ID of a form
$entry_id = 3; // ID of an entry
$entry = Forminator_API::get_entry( $form_id, $entry_id );
$file_url = $entry->meta_data['upload-1']['value']['file']['file_url'];
$file_path = $entry->meta_data['upload-1']['value']['file']['file_path'];
var_dump($entry); //contains paths and urls
Hope someone benefits.

How to use the key values of a prolog dict in a predicate?

I have a simple question which I'm getting a lot of trouble finding an answer.
I'm building an api that reads json and at the moment it successfully converts the json to a dict with http_read_json_dict. The problem is that, I have no clue how to access the attributes inside the dict and use that that data in a predicate. I tried following the swi-prolog documentation but to no avail... Do you guys know of a way?
I tried this to test read the content of the dict but I get a "key_value expected, found a dict" error. Please don't burn me at the stake:
json contains: [{"task":"learnprolog","dayofmonth":2}]
http_read_json_dict(Request, JSONIn,[json_object(term)]),
X = JSONIn,
format(user_output,"task is: ~p~n",[X.task]),
JSONOut=JSONIn.
But i was really hoping to do something like:
predicate(X):- X.dayofmonth==2,doSomething(X.task);doSomethingElse(X.task).
Thanks a lot for the help!
not sure about the details, without a server setup similar to what you're using... but
?- open_codes_stream(`[{"task":"learnprolog","dayofmonth":"2"}]`,S),json_read_dict(S,[J]),close(S),write(J.dayofmonth).
2
S = <stream>(0x7f5f14304dd0),
J = _G15591{dayofmonth:"2", task:"learnprolog"}.
note the square brackets around J

How do I work around cases where the listProvider data comes back as just ONE single record?

Im using HTTPservice to load XML and show the results in a list - it works when there are more than 1 XML record found.... but when there is only ONE single returned XML record it gets treated differently for some reason and generates this error:
Suspended: TypeError: Error #1034: Type Coercion failed: cannot convert mx.utils::ObjectProxy
I see posts like this:
http://anupushkaran.blogspot.com/2010/02/typeerror-error-1034-type-coercion.html
but I cant figure out how to adapt it to my HTTPService resultHandler code block...
Im using FB 4.6 and my XML structure looks like the following:
SiteXYZ
Events
EventListing
and all the data I want to use is under the EventListing Node.
I've tested some code that can detect when the length of whats returned so I think I can just detect when the length is 1 and then handle something differently -- not sure what though.
Another thing Im seeing that I think gets me close... when I look at the network monitor's TreeView > Response > Response Body I can see that on a succesful trip, the body comes back like:
SiteXYZ
Events
EventListing
[0]
[1].... and so on....
But on the cases where its a SINGLE record returned, the body of the response comes back like:
SiteXYZ
Events
EventListing
so shouldnt I be able to detect when its just ONE returned record and then set the list dataProvider accordingly? so that when its a lot of returned records the dataprovider is set with:
list1.dataProvider = myXML.lastResult.SiteXYZ.Events.EventListing;
but when its just ONE returned record, how would that dataProvider be set? this didnt work:
list1.dataProvider = lfXML.lastResult.LeisureFun.Events;
can anyone help with this? is my approach way off base? sorry for the rambling nature of the question but as I typed it, I stopped about 5 times and tried a number of things that came to mind as I thought through it... still nothing worked though... I feel like Im onto something (could be wrong though) but just cant solve it yet.
Answer was in the original website I referenced....
i took a closer look at what that post said the problem presented was and how that code snippet addressed it and was able to get it to work for me by putting it in my resultHandler block...
arr=new ArrayCollection();
if(event.result.SiteXYZ.Events.EventListing is ArrayCollection)
{
arr = ArrayCollection(event.result.SiteXYZ.Events.EventListing);
}
if(event.result.SiteXYZ.Events.EventListing is ObjectProxy)
{
arr =new ArrayCollection(ArrayUtil.toArray
(event.result.SiteXYZ.Events.EventListing));
}
now when there is one record returned it shows fine... same for multiple records returned.
thanks for the help though... I'll definately save this snippet for future use!