how to deal with JSON response - javascript

I'm using Python websockets to return JSON objects (I think) however I'm not sure how to deal with the response. I have an example using JavaScript which uses parseJSON, a snippet is bellow:
socket = io.connect("__socket address__");
socket.on("connect", function() {socket.emit("subscribe_areas", areas)});
var d = jQuery.parseJSON(c);
console.log(d);
d.type == "INTERPOSE";
which returns data I can access eg d.type == "INTERPOSE";:
Object {area: "BE", type: "MOVE", to: "0109", from: "0107", value: "2L65"}
Object {area: "BE", type: "MOVE", to: "0113", from: "0109", value: "2L65"}
where as my Python I recieve:
(u'{"area":"EH","type":"INTERPOSE","to":"B243","value":""}',)
(u'{"area":"EH","type":"INTERPOSE","to":"0337","value":""}',)
(u'{"area":"EH","type":"INTERPOSE","to":"0085","value":""}',)
Why does the python return JSON wrapped in brackets and commars? My Python is bellow:
from socketIO_client import SocketIO
import logging
import json
def on_connect():
print('CONNECTED')
areas = ['EH']
socketIO.emit('subscribe_areas', areas)
def on_message(*answer):
print(answer)
socketIO = SocketIO('_address_', _port_)
socketIO.on('connect', on_connect)
socketIO.on('message', on_message)
socketIO.wait()
I've tried decoding using json.load, json.loads, json.decode but recieve all sorts of errors. What am I missing and why is the return wrapped in brackets and such?

You told Python to expect 0 or more arguments:
def on_message(*answer):
print(answer)
Python then gives you a tuple of all arguments passed in; your print statements show you got one argument, so you got a tuple with just one element in it. That one element is a JSON string that you'd decode with json.loads().
Take the first element and decode that:
def on_message(*answer):
print(json.loads(answer[0]))
or don't use * and require that one argument is passed in, always and load from that one argument
def on_message(answer):
print(json.loads(answer))

Related

Eel function returns null

I was developing python program with Eel module.
But there is problem. It's that return null from eel.getImgSrc(path) function to get image's byte data.
Look at this code.
-----web/main.js------
async function run(path) {
let n = await eel.getImgSrc(path)() //path is correct. but n is null.
console.log(n);
}
-----app.py------
#eel.expose
def getImgSrc(path):
f = open(path, 'rb')
return f.read()
In Eel, the Python and JavaScript layers communicate by passing JSON back-and-forth. Internally, the Python side is passing your Python return value through a function that's defined like this: jsn.dumps(obj, default=lambda o: None) which results in the string null in your case. You can confirm this behavior by updating your code for debugging purposes only to something like this:
#eel.expose
def getImgSrc(path):
f = open(path, 'rb')
data = f.read()
print(json.dumps(data, default=lambda o: None))
return data
You'll see it prints out null. That's why you're seeing null on the JavaScript side.
I'm not a developer on the Eel project, so I can't explain the rationale of why this happens (I just see it in the source code). But now that you know it's happening, you can solve the problem by finding a way to encode your data so that it can be passed via JSON. (And you can use the sample code I posted above to check that it gets encoded properly.)
A search on the web for how to encode binary data into JSON with Python and decode with JavaScript will yield many results... so pick one that suits your particular needs. One way that's common (and is discussed in an issue on the Eel project website), is to base64 encode the data on the Python side and then decode it on the JavaScript side. It's not ideal, but is a workable solution that I've used in the past. Your code would be something like this...
-----web/main.js------
async function run(path) {
let n = await eel.getImgSrc(path)() // should no longer be null
console.log(atob(n));
}
-----app.py------
#eel.expose
def getImgSrc(path):
f = open(path, 'rb')
data = f.read()
data = base64.b64encode(data).decode("utf-8")
return data
Additionally, HTML image tags can accept base64 encoded data, so you could do something like:
async function run(path) {
let n = await eel.getImgSrc(path)() // should no longer be null
let imageEl = document.getElementById('image');
imageEl.src = "data:image/jpeg;base64," + n;
// any other processing...
}
You will probably need to tweak these examples to fit your exact needs.

Reading an Exported Javascript Object in Python

Is it possible to read/parse an exported Javascript or Typescript JSON-like object in Python?
For example:
In myJava.js:
export const myObj = {
entry: val
entry2: val2
...
}
In parseJava.py:
def parseJava():
# Some code to read in the javascript object
javaObjAsDictionary = someFunction("myJava.js")
Does such a "someFunction()" exist? If not, are there any clean ways around this?
Thanks in advance!
If you want to parse JSON, there is a library called JSON in Python 2 and 3 that does the encoding and decoding.
Specifically, you can use the json.loads or json.load methods to get a Python object (dictionary/list) from your JSON.
Something like:
import json
jsonDict = json.load("myJSON.json")
I am not sure exactly if this is what you need, hope this gives you a start.
# following code assumes that 'data.json' file exists in the current working directory
with open('data.json', 'r') as jsonFile: # opens JSON file in read only mode
# loads the content of JSON file and converts it into python dictionary object
dictionary = json.load(jsonFile)
print(dictionary)

Angular - parse json string created by json dumps

I couldn't find a helpful solution.
I work in python 3.6 (django rest-framwork) server side and angular 5 client side.
At the server:
class TypesView(APIView):
def get(self,request):
a = ['Cat','Dog']
j = json.dumps(a)
return Response(data=j, status=status.HTTP_200_OK)
I am trying to parse this at the client:
public getAnimalRaces(): Observable<string[]>{
const path = environment.apiEndpoint + "animals/races/"
return this._http_client.get<string[]>(path)
}
but I keep getting:
Error trying to diff '["Cat", "Dog"]'. Only arrays and iterables are allowed
This is what Being returned to the client:
"[\"Cat\", \"Dog\"]"
any ideas?
You are trying to iterate on a string.
You need to parse the response as JSON which will turn the response into an array which you can then use with *ngFor in the template for example.
this._http_client.get<string[]>(path)
.map((res) => JSON.parse(res));
Your response is stringified. In order to make it work, you have to send it as plain JSON on server side, or treat it as string and use JSON.parse() on client side.

Python & D3.js Dashboard Crossfilter Heat Map

I've successfully replicated this interactive dashboard map example here.
I now want to input my own data. My python is more simple than the example's since all my data is already structured in the way I want it.
Here's my python:
# -*- coding: utf-8 -*-
import pandas as pd
from shapely.geometry import Point, shape
from flask import Flask
from flask import render_template
import json
data_path = './input/'
def get_location(longitude, latitude, ny_json):
point = Point(longitude, latitude)
for record in ny_json['features']:
polygon = shape(record['geometry'])
if polygon.contains(point):
return record['properties']['Name']
return 'other'
with open(data_path + '/geojson/ny_HA.json') as data_file:
ny_json = json.load(data_file)
app = Flask(__name__)
#route to html index
#app.route("/")
def index():
return render_template("index.html")
#route data
#app.route("/data")
def get_data():
df = pd.read_csv(data_path + 'Mikes_NY_geocoded_tickets.csv', sep=';')
df['location'] = df.apply(lambda row: get_location(row['longitude'], row['latitude'], ny_json), axis=1)
cols_to_keep = ['timestamp', 'longitude', 'latitude', 'Violation', 'Type', 'DayOfWeek', 'location']
#remove NaN values
df_clean = df[cols_to_keep].dropna()
#return a json
return df_clean.to_json(orient='records')
if __name__ == "__main__":
app.run(host='0.0.0.0',port=5000,debug=True)
Here is my data geocoded_data.csv:
When I run my app python app.py, No errors and when I enter the localhost into my browser my dashboard appears, but everything is empty, my cross filters and map.
Here's what the browser is displaying:
Here are my errors in the browser console
Any ideas would be much appreciated.
Now that you've shown your JS code (in the debugger screenshot above), it's pretty easy to guess what is going wrong.
You have
d["timestamp"] = dateFormat.parse(d["timestamp"]);
d["timestamp"].setMinutes(0); // Error: d["timestamp"] is null
Here's the documentation for d3.time.format.parse():
Parses the specified string, returning the corresponding date object. If the parsing fails, returns null. Unlike "natural language" date parsers (including JavaScript's built-in parse), this method is strict: if the specified string does not exactly match the associated format specifier, this method returns null. For example, if the associated format is the full ISO 8601 string "%Y-%m-%dT%H:%M:%SZ", then the string "2011-07-01T19:15:28Z" will be parsed correctly, but "2011-07-01T19:15:28", "2011-07-01 19:15:28" and "2011-07-01" will return null, despite being valid 8601 dates.
You haven't shown what the value of d["timestamp"] is prior to conversion, but chances are that there is a subtle difference between the expected format and the actual format.
In particular, if the screenshot of your data is correct, there are no seconds in your date format, but your d3.time.format specifier is expecting them?

Interpolate string with dynamic data with angular2

I'm loading up data from the server via ajax requests. The JSON file has configurations for popups in the site.
popupData: {
data:{ var_one: "hello", var_two: "world"},
template: "the <b>{{var_two}}</b> say's {{var_one}}"
}
The variable names and template will be different for every occurrence of the popup.
How can I get this string interpolated with the data that comes with it? I need to pass the pre-built string to a component to be viewed using [innerHTML].
Somewhere after the data was received:
const popupString = popupData.template.replace(
/{{\s?([^{}\s]*)\s?}}/g,
(substring, parsedKey) => {
const replacer = popupData.data[parsedKey];
return typeof replacer !== 'undefined' ? replacer : substring;
}
);
It should equal the <b>world</b> says Hello in your example.
Please note that this code comes from robisim74’s angular-l10n (MIT license).

Categories

Resources