Announcement Announcement Module
Collapse
No announcement yet.
JSON in Roo, not displaying all properties, displaying some double Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JSON in Roo, not displaying all properties, displaying some double

    Hi, this is a bit of a follow-up on http://forum.springsource.org/showth...ngViewResolver

    While I'm waiting to find out how to do this via GWT, I'm doing my temperaments app with "classic" Roo, here's my app that's just started:

    Code:
    project --topLevelPackage com.saers.temperamentsapp --projectName TemperamentsApp --java 6 --template STANDARD_PROJECT
    persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY
    entity --class ~.domain.server.AppUser --testAutomatically 
    field string --fieldName username --notNull --sizeMin 3
    field string --fieldName passwordHash --notNull
    entity --class ~.domain.server.Device --testAutomatically 
    field string --fieldName UUID
    field string --fieldName name
    field boolean --fieldName willSync
    field date --fieldName lastSync --type java.util.Date
    field set --class ~.domain.server.AppUser --fieldName devices --element ~.domain.server.Device
    perform tests
    controller all --package ~.web
    security setup
    perform eclipse
    In webmvc-config.xml I've added:
    Code:
        <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
          <property name="mediaTypes">
            <map>
              <entry key="json" value="application/json"/>
            </map>
          </property>
          <property name="defaultViews">
            <list>
              <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
            </list>
          </property>
        </bean>
    and in pom.xml I've added


    Code:
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-lgpl</artifactId>
            <version>1.5.3</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-lgpl</artifactId>
            <version>1.5.3</version>
        </dependency>
    When I launch my app and create two devices for the AppUser and display my AppUser, I get the following JSON:

    Code:
    { "appuser" : 
      { "devices" : 
            [ { "deviceUUID" : "ZZ",
                "id" : 2,
                "lastSync" : null,
                "name" : "WW",
                "version" : 0,
                "willSync" : true
              },
              { "deviceUUID" : "XX",
                "id" : 1,
                "lastSync" : null,
                "name" : "YY",
                "version" : 0,
                "willSync" : true
              } ],
          "id" : 1,
          "passwordHash" : "njs",
          "username" : "njs",
          "version" : 0
        },
      "devices" : [ { "deviceUUID" : "XX",
            "id" : 1,
            "lastSync" : null,
            "name" : "YY",
            "version" : 0,
            "willSync" : true
          },
          { "deviceUUID" : "ZZ",
            "id" : 2,
            "lastSync" : null,
            "name" : "WW",
            "version" : 0,
            "willSync" : true
          }
        ]
    }
    Two questions:
    - I don't want to display some properties of my beans, for example passwordHash and version. What should I do to hide them away from my view?
    - Why is the set "devices" displayed twice, and what should I do to make this correctly just once as a part of the appuser?

    Cheers

    Nik

  • #2
    For my first question I should add that I was under the impression from the Jackson docs that I could annotate my variable with @JsonIgnore

    I have discovered that this does not work, hence my question, but since posing the question I have found that if I alter the Aspects, in this case located in AppUser_Roo_JavaBean, with the prefix @JsonIgnore, it is ignored the way I wanted, although only in the Json, it still appears everywhere else.

    Since my aspects are regenerated when I modify my class and thus any annotation there is thrown away, how should I handle this annotation correctly? And is there a way I can do this more general than just with @JsonIgnore?

    Cheers

    Nik

    Comment


    • #3
      Hi Nik,

      I have just tried out your application and it works for me .


      I have discovered that this does not work, hence my question, but since posing the question I have found that if I alter the Aspects, in this case located in AppUser_Roo_JavaBean, with the prefix @JsonIgnore, ...

      Since my aspects are regenerated when I modify my class and thus any annotation there is thrown away, how should I handle this annotation correctly?
      Yes, as per our documentation Roo actively maintains all aspects (.aj files). This means, if you want to customize the behaviour of code in an aspect you need to push-in that code into your java source file.

      AJDT, which is included in the SpringSource Tool Suite allows you to do this automatically through a context menu (see more info about this in the documentation). Roo will not change your java sources so it is safe for you to push in the getVersion() method and annotate that with @JsonIgnore.

      it is ignored the way I wanted, although only in the Json, it still appears everywhere else.
      Can you elaborate further what exactly you mean by everywhere else? The Roo MVC scaffolding is currently not aware of Json specific annotations, so it would not be able to act upon them. As you noted, you have added the json support manually, not through Roo. If you want json support through Roo please comment and vote here: https://jira.springsource.org/browse/ROO-844.

      .. is there a way I can do this more general than just with @JsonIgnore?
      Since you have chosen to use Jackson for JSON binding I guess you would need to consult the project documentation to see if other options exist.

      Another option which allows you full control over the JSON document you are returning is to take a look at Spring's new @ResponseBody support: http://static.springsource.org/sprin...n-responsebody

      HTH,
      Stefan

      Comment


      • #4
        Hi Stefan,
        Thank you very much for getting back to me. :-)

        I realize the post was quite filled with Jackson and JSON, but my first question (and the reference to "everywhere else") is actually more general: can I give Roo some instructions too or annotate fields directly in my source code to ensure that some properties, such as passwordHash, are never presented in a generated view?

        Thank you very much for the hint about pushing code into the Java files, I hadn't thought about that.

        When you say you got it working correctly, does that mean that you did not get the list "devices" twice?

        Cheers

        Nik

        Comment


        • #5
          About not presenting certain fields in the view: each Roo tag has a render attribute which can be set to false, resulting in the form element being omitted. The main thing here is to keep an element (any element really) with the field id Roo expects so that the jspx roundtripping still works.

          About the Jackson generated json, I don't know either off hand . Maybe you can ask on their forum / list?

          -Stefan

          Comment


          • #6
            Hi Stefan,
            again many thanks for your prompt feedback. :-)

            I'll be sure to ask the jackson rendering questions on their forums. :-)

            Regarding the render attribute, I found what you say in the documentation http://static.springsource.org/sprin.../base-web.html
            Most default tags installed by Roo have a render attribute which is of boolean type. This allows users to completely disable the rendering of a given tag (and potential sub tags). This is useful in cases where you don't wish individual fields in a form to be presented to the user but rather have them autopopulated through other means (ie input type="hidden"). The value of the render attribute can also be calculated dynamically through the Spring Expression Language (SpEL) or normal JSP expression language. The generated create.jspx in Roo application demonstrates this.
            I still don't quite understand, though, I tried:

            Code:
            field string --fieldName hidden --render false --class ~.data.entities.TestEntity
            and I couldn't see anything that indicated that it should be hidden and it was displayed in the rendered web controller. All the Roo tags in my TestEntity are on the entity level (I couldn't find an attribute that looked like render on any of them), and I want to hide it on property level. What Roo tags can I add to my property and what is the attribute name that I can set to false?

            Cheers

            Nik

            Comment

            Working...
            X