3

Hi I am trying to display nested JSON data in my view, similar to how it appears in the Advanced REST Client when you get a response from an API.

I found this question which basically asks the same thing I am asking; however, I want to display the result in a view using the Play Framework 2.3.x. I know that I need a recursive function to display all the json objects, so I've tried using a reusable block in my view. Here's what I have right now:

@(fromAPI: com.fasterxml.jackson.databind.JsonNode)

@import com.fasterxml.jackson.databind.JsonNode

@walkJsonTree(name: String, node: JsonNode) = {

    @if(node.isObject()) {

        @for(nodeEntry <- node.fields()) {
            <li>@nodeEntry.getKey(): </li>
            <ul>@walkJsonTree(nodeEntry.getKey(), nodeEntry.getValue())</ul>
        }
    }
    @if(node.isArray()) {
        @for(arrayNode <- node.fields()) {
            <li>[List]: </li>
            <ul>@walkJsonTree(arrayNode.getKey(), arrayNode.getValue())</ul>
        }
    }
    @if(node.isValueNode()) {
        <li>@node.asText()</li>
    } else {
        @* other *@
        <li>@node.asText()</li>
    }

}

@main("API Response") {

    <div class="container">
        <h3>API Response</h3>

        <ul>
            @walkJsonTree(null, fromAPI)
        </ul>
    </div>
}

Unfortunately, this is not displaying the JSON properly. It only displays the first object's name based on this line <li>@nodeEntry.getKey(): </li>. What am I doing wrong? Does anyone have any other suggestions for displaying JSON in a nested manner?

Thanks!

Community
  • 1
  • 1
KJ50
  • 765
  • 1
  • 10
  • 27

1 Answers1

1

I had the "array" if block wrong. It should use the elements() function rather than fields(). Here is an updated version of my code, with this refactor and other cleanup of <ul> and <li> elements

@(fromAPI: com.fasterxml.jackson.databind.JsonNode)

@import com.fasterxml.jackson.databind.JsonNode

@walkJsonTree(name: String, node: JsonNode) = {

    @if(node.isObject()) {
        <ul>
            @for(nodeEntry <- node.fields()) {
                <li>@nodeEntry.getKey(): @walkJsonTree(nodeEntry.getKey(), nodeEntry.getValue())</li>
            }
        </ul>
    }
    @if(node.isArray()) {
        <ul>
            @for(arrayNode <- node.elements()) {
                <li>[List]: @walkJsonTree(name, arrayNode)</li>
            }
        </ul>
    }
    @if(node.isValueNode()) {
        @node.asText()
    } else {
        @* other *@
        @node.asText()
    }

}

@main("API Response") {

    <div class="container">
        <h3>API Response</h3>
        @walkJsonTree(null, fromAPI) 
    </div>
}

This could probably still be improved aesthetically, but it satisfies the minimum amount of functionality that I wanted

KJ50
  • 765
  • 1
  • 10
  • 27