简体   繁体   中英

How to convert a python list of tuples to an array in JavaScript?

I am trying to make a website using Flask, where I pass in HTML canvas data to a database and then use that data in another route. When I retrieve the data from the database, it's in the form of a list, here's an example of that list with only one element :

[(1, 'circle', '{"pencil":[{"startx":346,"starty":105,"endx":346,"endy":105,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":344,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":341,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":333,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":330,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":109,"thick":2,"color":"#000000"}],"line":[],"rectangle":[],"circle":[],"eraser":[]}', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu4AAAHCCAYAAACwm0waAAAAAXNSR0IArs4c6QAAIABJREFUeF7t3W2SI9lVBuDr/vD8gOgmAsLegNkGrB22Ke4KQjEiAAAECBAgQIEBAcbcHCBAgQIAAAQIECCQQ+D/vr4ThKs0KewAAAABJRU5ErkJggg==', '10', '10', '100', '100')]

Following several previous answers given in this type of question, I tried the following approach, first I used json.dumps() :

In Flask:

files = json.dumps(files)
return render_template("edit.html", files=files)

In edit.html , I pass it into a function simply as:

<button id="show" onclick="loadImages(`{{ files }}`)">View</button>

Finally in edit.js , I try to read it in an array as follows:

function loadImages(sources) {
    var canvas = document.getElementById("paint");    
    var ctx = canvas.getContext("2d");

    console.log(sources);
    
    sources = JSON.parse(sources);
    console.log(typeof(sources)); 
    for(var i = 0; i < sources.length; i++) {
        ctx.drawImage(sources[i][3], sources[i][4], sources[i][5], sources[i][6], sources[i][7]);
    
    }
  }

But this returns an error:

Uncaught SyntaxError: Unexpected token p in JSON at position 18
    at JSON.parse (<anonymous>)
    at loadImages (edit.js:16)
    at HTMLButtonElement.onclick (edit:39)

The output of the console.log(sources) in the loadImages function is :

[[1, "circle", "{"pencil":[{"startx":346,"starty":105,"endx":346,"endy":105,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":344,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":341,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":333,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":330,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":326,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":326,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":322,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":319,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":317,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":315,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":314,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":312,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":311,"endy":105,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":310,"endy":106,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":308,"endy":106,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":307,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":306,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":304,"endy":109,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":302,"endy":110,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":301,"endy":111,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":109,"thick":2,"color":"#000000"}],"line":[],"rectangle":[],"circle":[],"eraser":[]}", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu4AAAHCCAYAAACwm0waAAAAAXNSR0IArs4c6QAAIABJREFUeF7t3W2SI9lVBuDr/vD8gOgmAsLegNkGrB22ARuAgAimDT/G022ItCuH7LRUkkpS3vPxTITDMK5Snvu8N1VvZ6eyfjX8Q4AAAQIECBAgQIBAeIFfhZ/QgAQIECBAgAABAgQIDMXdJiBAgAABAgQIECCQQEBxTxCSEQkQIECAAAECBAgo7vYAAQIECBAgQIAAgQQCinuCkIxIgAABAgQIECBAQHG3BwgQIECAAAECBAgkEFDcE4RkRAIECBAgQIAAAQKKuz1AgAABAgQIECBAIIGA4p4gJCMSIECAAAECBAgQUNztAQIECBAgQIAAAQIJBBT3BCEZkQABAgQIECBAgIDibg8QIECAAAECBAgQSCCguCcIyYgECBAgQIAAAQIEFHd7gAABAgQIECBAgEACAcU9QUhGJECAAAECBAgQIKC42wMECBAgQIAAAQIEEggo7glCMiIBAgQIECBAgAABxd0eIECAAAECBAgQIJBAQHFPEJIRCRAgQIAAAQIECCju9gABAgQIECBAgACBBAKKe4KQjEiAAAECBAgQIEBAcbcHCBAgQIAAAQIECCQQUNwThGREAgQIECBAgAABAoq7PUCAAAECBAgQIEAggYDiniAkIxIgQIAAAQIECBBQ3O0BAgQIECBAgAABAgkEFPcEIRmRAAECBAgQIECAgOJuDxAgQIAAAQIECBBIIKC4JwjJiAQIECBAgAABAgQUd3uAAAECBAgQIECAQAIBxT1BSEYkQIAAAQIECBAgoLjbAwQIECBAgAABAgQSCCjuCUIyIgECBAgQIECAAAHF3R4gQIAAAQIECBAgkEBAcU8QkhEJECBAgAABAgQIKO72AAECBAgQIECAAIEEAop7gpCMSIAAAQIECBAgQEBxtwcIECBAgAABAgQIJBBQ3BOEZEQCBAgQIECAAAECirs9QIAAAQIECBAgQCCBgOKeICQjEiBAgAABAgQIEFDc7QECBAgQIECAAAECCQQU9wQhGZEAAQIECBAgQICA4m4PECBAgAABAgQIEEggoLgnCMmIBAgQIECAAAECBBR3e4AAAQIECBAgQIBAAgHFPUFIRiRAgAABAgQIECCguNsDBAgQIECAAAECBBIIKO4JQjIiAQIECBAgQIAAAcXdHiBAgAABAgQIECCQQEBxTxCSEQkQIECAAAECBAgo7vYAAQIECBAgQIAAgQQCinuCkIxIgAABAgQIECBAQHG3BwgQIECAAAECBAgkEFDcE4RkRAIECBAgQIAAAQKKuz1AgAABAgQIECBAIIGA4p4gJCMSIECAAAECBAgQUNztAQIECBAgQIAAAQIJBBT3BCEZkQABAgQIECBAgIDibg8QIECAAAECBAgQSCCguCcIyYgECBAgQIAAAQIEFHd7gAABAgQIECBAgEACAcU9QUhGJECAAAECBAgQIKC42wMECBAgQIAAAQIEEggo7glCMiIBAgQIECBAgAABxd0eIECAAAECBAgQIJBAQHFPEJIRCRAgQIAAAQIECCju9gABAgQIECBAgACBBAKKe4KQjEiAAAECBAgQIEBAcbcHCBAgQIAAAQIECCQQUNwThGREAgQIECBAgAABAoq7PUCAAAECBAgQIEAggYDiniAkIxIgQIAAAQIECBBQ3O0BAgQIECBAgAABAgkEFPcEIRmRAAECBAgQIECAgOJuDxAgQIAAAQIECBBIIKC4JwjJiAQIECBAgAABAgQUd3uAAAECBAgQIECAQAIBxT1BSEYkQIAAAQIECBAgoLjbAwQIECBAgAABAgQSCCjuCUIyIgECBAgQIECAAAHF3R4gQIAAAQIECBAgkEBAcU8QkhEJECBAgAABAgQIKO72AAECBAgQIECAAIEEAop7gpCMSIAAAQIECBAgQEBxtwcIECBAgAABAgQIJBBQ3BOEZEQCBAgQIECAAAECirs9QIAAAQIECBAgQCCBgOKeICQjEiBAgAABAgQIEFDc7QECBAgQIECAAAECCQQU9wQhGZEAAQIECBAgQICA4m4PECBAgAABAgQIEEggoLgnCMmIBAgQIECAAAECBBR3e4AAAQIECBAgQIBAAgHFPUFIRiRAgAABAgQIECCguNsDBAgQIECAAAECBBIIKO4JQjIiAQIECBAgQIAAAcXdHiBAgAABAgQIECCQQEBxTxCSEQkQIECAAAECBAgo7vYAAQIECBAgQIAAgQQCinuCkIxIgAABAgQIECBAQHG3BwgQ6CLwxzHGke95X8cYH7vgWicBAgQIPF/gyB9iz1+NIxAgQODPAj+OMT4FwfjfMca7ILMYgwABAgQSCyjuicMzOgECJwVeK+1HlOifxxgfdpMtV/vfy4sAAQIECNwggg==", "10", "10", "100", "100"]]

I tried multiple approaches to get this done, but this was the closest I could reach to what I want, how do I proceed to correct this?

I found few problems in this code - all with template:

  1. template in flask escapes data (to make it safer) so using {{ file }} it creates HTML with

     [[1, &#34;circle&#34;, &#34;{\\&#34;pencil\\&#34;:[

    You can see it in browser if you use Show Page Source ( Ctrl+U ).

    It needs {{ file|safe }} to create correct HTML

     [[1, "circle", "{\\"pencil\\":[
  2. it doesn't need ticks in loadImages( ``...`` )

  3. because files puts string with " " so loadImage has to be in ' '

     onclick='loadImages({{ files|safe }})'
  4. browser treats text from files as normal code so it parses data at loading and it doesn't need JSON.parse()

  5. to draw image you have to create Image and assign data to .src

     var img = new Image(); img.src = sources[i][3]; ctx.drawImage(img, ...)

Minimal working code

EDIT:

You don't have to use json.dumps(data) but {{ data|tojson }}

Eventually you can use {{ data|safe }} but it will need to change some " " into ' ' .

from flask import Flask, request, render_template_string
import json

app = Flask(__name__)

data = [(1, 'circle',
         '{"pencil":[\
             {"startx":346,"starty":105,"endx":346,"endy":105,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":344,"endy":104,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":341,"endy":103,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":338,"endy":103,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":336,"endy":103,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":333,"endy":103,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":330,"endy":103,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":336,"endy":107,"thick":2,"color":"#000000"},\
             {"startx":346,"starty":105,"endx":336,"endy":109,"thick":2,"color":"#000000"}],\
          "line":[],"rectangle":[],"circle":[],"eraser":[]\
         }',
         'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAAAAACoWZBhAAAAMklEQVR4nEXNwQkAMBACwfFI/y2bxwXia8FFUwF1pCCNJTIIwaD04ctsKRyaldI/9i8u1iwOE6FA880AAAAASUVORK5CYII=',
         '10', '10', '10', '10'
)]

@app.route('/', methods=['GET', 'POST'])
def index():
    text = json.dumps(data)
    return render_template_string('''
<script>
function loadImages(sources) {
    console.log(sources);

    var canvas = document.getElementById("paint");    
    var ctx = canvas.getContext("2d");
    
    for(var i = 0; i < sources.length; i++) {
        var data = sources[i]
        console.log(data[3]);
        var img = new Image();
        img.src = data[3];
        ctx.drawImage(img, data[4], data[5]); //, data[6], data[7]);
    }
}
</script>

<body>
<h1>files</h1>
<pre>{{ files }}</pre>
<h1>files|safe</h1>
<pre>{{ files|safe }}</pre>
<h1>files|tojson</h1>
<pre>{{ files|tojson }}</pre>
<hr>

<canvas id="paint" width="100" height="100"></canvas><br/>

<button id="show" onclick='loadImages({{ files|safe <button id="show" onclick='loadImages({{ files|safe }})'>View files|safe</button>

<button id="show" onclick='loadImages({{ data|tojson }})'>View data|tojson</button>

<button id="show" onclick="loadImages({{ data|safe }})">View data|safe</button>

</body>
''', files=text, data=data)
if __name__ == '__main__':
    #app.debug = True 
    app.run()

For your data:image I get error image broken so I use my small icon 10x10

在此处输入图片说明

but I don't know why but sometimes I have to click button two times to see image.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM