3

If a string looks like a number, eg. 111 CXF doesn't return it as string, but as number.

<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
    <property name="serializeAsArray" value="true" />
    <property name="arrayKeys" ref="jsonKeys" />
</bean>

As one can see, I use the JSON provider. How can I force it, to deliver correct JSON strings?

{object:{"name":"111"}} instead of {object:{"name":111}}

Thanks in advance...

Nabor
  • 1,661
  • 3
  • 20
  • 45

2 Answers2

6

You can add SimpleConverter to your JSONProvider so that it will not convert strings to numbers. By Default it uses DefaultConverter. But make sure that relevant bean as type string for the field.

<bean id="simpleConverter" class="org.codehaus.jettison.mapped.SimpleConverter"/>

<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
    <property name="typeConverter" ref="simpleConverter"/>
</bean>

You can find more information about this defect in Jettison http://jira.codehaus.org/browse/JETTISON-61 http://jira.codehaus.org/browse/JETTISON-36

user1969807
  • 91
  • 1
  • 1
4

EDIT: This seems to be a bug in Jettison. org.apache.cxf.jaxrs.provider.json.JSONProvider uses Jettison which caused this issue. If you use Jackson provider, then this issue is no longer there.

Add the following to beans.xml under jaxrs:server.

     <jaxrs:providers>
                <ref bean="jacksonProvider" />
        </jaxrs:providers>

.

And, the following directly as a child of root.

<bean id="jacksonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider">

</bean>

As per the JSON Specification, numbers are allowed as values. An excerpt from it says,

2.1. Values

A JSON value MUST be an object, array, number, or string, or one of the following three literal names:

  false null true

Here's an example that is mentioned in the spec.

   {
      "Image": {
          "Width":  800,
          "Height": 600,
          "Title":  "View from 15th Floor",
          "Thumbnail": {
              "Url":    "http://www.example.com/image/481989943",
              "Height": 125,
              "Width":  "100"
          },
          "IDs": [116, 943, 234, 38793]
        }
   }

If you actually want a String, then you probably look at your resource class, and relevant bean class to make sure the field types are correct!

Community
  • 1
  • 1
Kasun Gajasinghe
  • 2,735
  • 1
  • 21
  • 30
  • As mentioned in my Question, in Java all object properties I talk about are String! so I don't expect, that CXF returns a Number as a String, I expect, that it returns a String as a String. But what it does is, it returns the String "111" as Number 111 – Nabor Jun 11 '12 at 19:53
  • Alright, so I guess the relevant bean class, and resource is configured to haveStrings. Are you getting marshalling erorrs when there are integers for the key `name`? The provided response in the question was the response content body, right? – Kasun Gajasinghe Jun 12 '12 at 07:53
  • You can reproduce it. Create a Maven projekt. The following pom.xml should be used: http://pastebin.com/01Y5QW3F. In addition use this beans.xml: http://pastebin.com/BkDu84qp. web.xml http://pastebin.com/Q1zLSd3a and this to Java files: http://pastebin.com/xLCwENkf & http://pastebin.com/tgY3ZKZw. If you then start the server and call http://localhost:8080/services you get this JSON: {"attribute":{"firstname":"User","lastname":123}}. But as you see in the Java code, 123 is a String. – Nabor Jun 12 '12 at 19:36
  • I haven't had a time to test this yet, but you may try using the return type as Response for getTest. You can of course add your bean instance (Test) there. Something like `return Response.ok().entity( new Test().setFirstname("User").setLastname("123") ).type(MediaType.APPLICATION_JSON).build()` – Kasun Gajasinghe Jun 13 '12 at 13:18
  • The Return type is set globally at the endpoint. It works fine, it returns JSON but it creates Strings as Number ;). Using Response doesn't change anything, I have it already that way in my project... It looks like a Bug in CXF... – Nabor Jun 13 '12 at 13:47
  • Yes, this seems to bug. I was able to consistently reproduce this. Strangely, if the number is preceded by a zero (say 0123), then its interpreted as a String. – Kasun Gajasinghe Jun 13 '12 at 15:28
  • Where can this bug be reported? – Nabor Jun 13 '12 at 17:58
  • @user1177897 I have updated the answer with a possible alternative. The solution is to use Jackson instead of Jettison for json marshalling/unmarshalling. I think the bug should be reported against Jettison. – Kasun Gajasinghe Jun 14 '12 at 01:58
  • I tried Jackson already but it generates different JSON. The Problem is, that the client currently depends on the JSON Layout. Jackson per default does not create {"object":{"property":"value"}} it creates {"property":"value"}. I expect, that this can be configured, but in the current project phase I don't want to change a major component. – Nabor Jun 14 '12 at 08:26