I have a set of lists in my python Flask server, namely c_data
, data
, targetx
, targety
, sizex
and sizey
. They look something like the following:
c_data: ['{"pencil":[[{"startx":183,"starty":165,"endx":183,"endy":167,"thick":2,"color":"#000000"},{"startx":183,"starty":167,"endx":187,"endy":169,"thick":2,"color":"#000000"},{"startx":187,"starty":169,"endx":188,"endy":171,"thick":2,"color":"#000000"},{"startx":188,"starty":171,"endx":190,"endy":172,"thick":2,"color":"#000000"},{"startx":190,"starty":172,"endx":190,"endy":174,"thick":2,"color":"#000000"},{"startx":190,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"},{"startx":191,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"}]],"line":[],"rectangle":[],"circle":[],"eraser":[],"last_action":[0]}']
data: ['data:image/png;base64,iVBORw0KG.......(basically a very long string of base64 encoding)]
targetx: [369]
targety: [252]
sizex: [100]
sizey: [100]
(The c_data
is declared in the js file as canvas_data = {"pencil": [], "line": [], "rectangle": [], "circle": [], "eraser": [], "last_action": [] };
, this may help you understand the structure of c_data
better)
How do I pass these lists so that I can then read them again in JS?
Here's what I tried, in the app.py
file, I first did the following to send the data to the scripts:
c_data = json.dumps(c_data)
data = json.dumps(data)
targetx = json.dumps(targetx)
targety = json.dumps(targety)
sizex = json.dumps(sizex)
sizey = json.dumps(sizey)
return jsonify({'result': 'success', 'c_data': c_data, 'data': data, 'targetx': targetx, 'targety': targety, 'sizex': sizex, 'sizey': sizey})
and I pass it to Jinja by rendering HTML, and I also have a function in JavaScript called pencil()
, using which I tried something like this:
<body onl oad="pencil(`{{ c_data }}`, `{{ data }}`, `{{ targetx }}`, `{{ targety }}`, `{{ sizex }}`, `{{ sizey }}`)">
and in my script.js, I used the passed data in the following way to read them:
async function loadImages(c_data, data, targetX, targetY, targetWidth, targetHeight) {
c_data = c_data.replace(/'/g, '"');
data = data.replace(/'/g, '"');
targetX = targetX.replace(/'/g, '"');
targetY = targetY.replace(/'/g, '"');
targetWidth = targetWidth.replace(/'/g, '"');
targetHeight = targetHeight.replace(/'/g, '"');
c_data = JSON.parse(c_data);
data = JSON.parse(data);
targetX = JSON.parse(targetX);
targetY = JSON.parse(targetY);
targetWidth = JSON.parse(targetWidth);
targetHeight = JSON.parse(targetHeight);
for (var i = 0; i < data.length; i ) {
var tx = parseInt(targetX[i]);
var ty = parseInt(targetY[i]);
var tw = parseInt(targetWidth[i]);
var th = parseInt(targetHeight[i]);
var img = {
src: await loadImage(data[i], i),
c_data: c_data[i],
ul: {
x: tx,
y: ty
},
ur: {
x: tx tw,
y: ty
},
ll: {
x: tx,
y: ty th
},
lr: {
x: tx tw,
y: ty th
}
};
images.push(img)
}
draw_canvas();
}
Using this approach, all the data works fine except c_data
, which does not get converted to the canvas_data
object type which I was expecting and has some backslashes in its string. And when I try to remove the backslashes using the line c_data = c_data.replace(/\\/g, '');
I get the error:
Uncaught (in promise) SyntaxError: Unexpected token p in JSON at position 4
How do I correctly parse the above data types to JS and read them?
CodePudding user response:
It's a little difficult to deduce your code from your explanations.
If you omit json.dumps
on the server, you don't have to parse the data again in the browser. This eliminates the then unnecessary calls of JSON.parse
.
Data can be passed from Flask to JavaScript in a number of ways.
1) Using the tojson filter:
One possibility is to transfer the data to the template as usual and then convert it to JSON with the Jinja filter tojson
.
from flask import (
Flask,
render_template
)
app = Flask(__name__)
@app.route('/')
def index():
c_data = {
"pencil":[
[
{"startx":183,"starty":165,"endx":183,"endy":167,"thick":2,"color":"#000000"},
{"startx":183,"starty":167,"endx":187,"endy":169,"thick":2,"color":"#000000"},
{"startx":187,"starty":169,"endx":188,"endy":171,"thick":2,"color":"#000000"},
{"startx":188,"starty":171,"endx":190,"endy":172,"thick":2,"color":"#000000"},
{"startx":190,"starty":172,"endx":190,"endy":174,"thick":2,"color":"#000000"},
{"startx":190,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"},
{"startx":191,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"}
]
],
"line":[],
"rectangle":[],
"circle":[],
"eraser":[],
"last_action":[0]
}
data = 'data:image/png;base64,iVBORw0KG.......(basically a very long string of base64 encoding)'
targetx = [369]
targety = [252]
sizex = [100]
sizey = [100]
return render_template('index.html', **locals())
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
((cData, data, targetX, targetY, sizeX, sizeY) => {
function pencil(cData, data, targetX, targetY, sizeX, sizeY) {
console.log(cData, data, targetX, targetY, sizeX, sizeY);
}
document.addEventListener('DOMContentLoaded', () => {
pencil(cData, data, targetX, targetY, sizeX, sizeY);
});
})(
{{ c_data | tojson }},
{{ data | tojson }},
{{ targetx | tojson }},
{{ targety | tojson }},
{{ sizex | tojson }},
{{ sizey | tojson }}
);
</script>
</body>
</html>
2) Get data converted with jsonify:
Another possibility is to obtain the data from another endpoint via AJAX. The data is converted into JSON format on the server side using jsonify
.
from flask import (
Flask,
render_template,
jsonify
)
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/data')
def data():
c_data = {
"pencil":[
[
{"startx":183,"starty":165,"endx":183,"endy":167,"thick":2,"color":"#000000"},
{"startx":183,"starty":167,"endx":187,"endy":169,"thick":2,"color":"#000000"},
{"startx":187,"starty":169,"endx":188,"endy":171,"thick":2,"color":"#000000"},
{"startx":188,"starty":171,"endx":190,"endy":172,"thick":2,"color":"#000000"},
{"startx":190,"starty":172,"endx":190,"endy":174,"thick":2,"color":"#000000"},
{"startx":190,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"},
{"startx":191,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"}
]
],
"line":[],
"rectangle":[],
"circle":[],
"eraser":[],
"last_action":[0]
}
data = 'data:image/png;base64,iVBORw0KG.......(basically a very long string of base64 encoding)'
targetx = [369]
targety = [252]
sizex = [100]
sizey = [100]
return jsonify(
c_data=c_data,
data=data,
targetx=targetx, targety=targety,
sizex=sizex, sizey=sizey
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
(async (uri) => {
function pencil(cData, data, targetX, targetY, sizeX, sizeY) {
console.log(cData, data, targetX, targetY, sizeX, sizeY);
}
const dat = await fetch(uri).then(resp => resp.json());
const { c_data, data, targetx, targety, sizex, sizey } = dat;
pencil(c_data, data, targetx, targety, sizex, sizey);
})({{ url_for('data') | tojson }});
</script>
</body>
</html>