2

I'm struggling with printing a formatted JSON response from Watson's NLU API. I'm using Python 2.7 and Django 1.11. My views.py looks like this:

def nlu_analysis(request):
    if request.method == 'POST':
        text2send = request.POST.get('text2send')
        natural_language_understanding = NLUV1(
            version='2017-02-27',
            username='####',
            password='####')

    response = natural_language_understanding.analyze(
        text=text2send,
        features=[features.Entities(), ... features.SemanticRoles()])

        parsedData = json.dumps(response, indent=2)
    return render(request, 'analysis.html', {'data': parsedData})

My analysis.html looks like this:

  <div class="container text-left">
      <p>{{ data }}</p>
  </div>

The result of all of this is the data, with JSON brackets being printed on one line like this:

{ "semantic_roles": [ { "action": { "text": "are", "verb": { "text": "be", "tense": "present" }, "normalized": "be" }, "sentence": "Batman and Superman are fighting the bad guys", ... "keywords": [ { "relevance": 0.931284, "text": "bad guys" }, { "relevance": 0.790756, "text": "Superman" }, { "relevance": 0.752557, "text": "Batman" } ] }

If I run this within a for loop

<div class="container text-left">
    {% for d in data %}
        <p>{{ d }}</p>
    {% endfor %}
</div>

it simply prints on character on each line

{

"

s

e

m

...

suggesting that {{ data }} is a string, nothing more.

Clearly I am fundamentally misunderstanding something. Either it is something with respect to how json.dumps (including 'indent=2') works or how to deal with it properly in my template. I suspect the later as the information being passed via 'data' clearly contains all of the JSON syntax. If I place the one line result above result in a JSON validator it reformats and validates perfectly.

Any help for a complete rookie out there? Thanks.

sctoy
  • 37
  • 6
  • 1
    Why do you json dump the data before passing it to the template? Your for loop will work perfectly without it – Aswin Murugesh Jun 03 '17 at 15:55
  • Sure enough removing the json.dumps got me a lot closer, but it only gets me the top level of the JSON feed. How do I get to each level of the JSON feed? Thanks so much Aswin. – sctoy Jun 03 '17 at 16:03
  • In the example above when I added the for loop it printed 'semantic_roles' and 'keywords' from the example above. Not the next level down. Thanks again. – sctoy Jun 03 '17 at 16:10
  • For that you will just need to nest your for loops similarly how you would access them with normal python code – Aswin Murugesh Jun 03 '17 at 16:17

2 Answers2

2

Why are you even parsing your response. json.dumps converts the dict object to string. You can instead directly use it as return render(request, 'analysis.html', {'data': response}).

Nikhil Rajawat
  • 121
  • 1
  • 4
0

If you want to access the value for a key in the dict object, you just need to do like this (for your example data),

{{ response.semantic_roles }}

Here semantic_roles will be interpreted as a literal string and not using the value of the variable “semantics”, if one exists in the template context. And response is the name of the context variable.

Or, If you want to get value of each key in he dict object using a loop, you may need to create a custom filter for your template,

from django.template.defaulttags import register

@register.filter
def get_item(dictionary, key): 
    return dictionary.get(key)

And in your template,

{% for key in response %}
{{ response|get_item:key }}
{% endfor %}

Of course, make sure to call load on your template tags so they're visible to the renderer.

Here are some helpful links,

zaidfazil
  • 9,017
  • 2
  • 24
  • 47