问题:CXF 结合jaxb返回json字符串时,当属性为数值型字符串时,没有双引号问题。
这个问题应该是影响比较大的,网上的资料并不多,其中比较有帮助的是?http://fly2wind.iteye.com/blog/730350
?
?
不得不同意,JavaBean 转 XML后 再转JSON,会丢失类型,作为 org.codehaus.jettison.mapped.DefaultConverter 采取的补救措施是,将数字转为数字类型,但也会秒杀了字符型且值为数字的对象。
?
作为解决方案,这个思路是很好的,先将字符串加个特殊标志,然后再用转换器去掉特殊标志。
?
但大多数人都会认会需要改底层代码比较不现实,有没有一种方式更安全一些。
?
这几天我也作了一些尝试,比如按网友的说法,改了 JAXB 的底层,配置了转换器,也能成功地跑出结果,但更大的杯具发生了。这个方法只能将根一级的变量值返回正确,如果是javaBean ?中的变量是引用的其他Bean,列表... 都不能正确得到结果。
?
我也采用了扩展一个新的 JSONProvider,JAXBElementProvider ,预先递归将字符全部加上特殊标志,或许能得到正确的结果。
?
但这些方法或许不是最好。
?
终于有比较简洁的方法:
以 CXF 为例,配置文件。
?
?
<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider"> <property name="serializeAsArray" value="true"/> <property name="arrayKeys" ref="jsonKeys"/> <property name="produceMediaTypes" ref="jsonTypes"/> <property name="consumeMediaTypes" ref="jsonTypes"/> <property name="ignoreNamespaces" value="true"/> <property name="dropRootElement" value="true"/> <property name="ignoreMixedContent" value="true"/> <property name="attributesToElements" value="true"/> </bean>?
给 JavaBean 的字符型变量中加多一个声明: @XmlAttribute
?
/** * 留言标题/短内容. * Field: subject */ @Size(max = 32) @XmlAttribute private java.lang.String subject; /** * 留言主体/长内容. * Field: body */ @Size(max = 255) @XmlAttribute private java.lang.String body;
?
这样就能得到想要的结果了,多少层级引用的对象都可以。
?
{ "msg": "OK", "ret": 0, "err": 0, "message": { "subject": "1", "body": "1", "id": 423, "userId": 1, "clientVersion": 1, "sentId": 1, "receiptId": 1, "threadId": 275, "status": 0, "creationDate": 1338361215759, "modificationDate": 1338361215759, "usn": 710 } }?
完整 cxf 配置文件
?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <util:list id="jsonKeys"> <value>forumThreads</value> <value>forumMessages</value> <value>forumUserStatis</value> </util:list> <util:list id="jsonTypes"> <value>application/json</value> <value>application/jettison</value> </util:list> <bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider"> <property name="serializeAsArray" value="true"/> <property name="arrayKeys" ref="jsonKeys"/> <property name="produceMediaTypes" ref="jsonTypes"/> <property name="consumeMediaTypes" ref="jsonTypes"/> <property name="ignoreNamespaces" value="true"/> <property name="dropRootElement" value="true"/> <property name="ignoreMixedContent" value="true"/> <property name="attributesToElements" value="true"/> </bean> <jaxrs:server id="restApiResource" address="/"> <jaxrs:serviceBeans> <!-- <ref bean="userAuthServiceResource"/> <ref bean="syncServiceResource"/> <ref bean="imageServiceResource"/> <ref bean="messageServiceResource"/> <ref bean="upgradeServiceResource"/> --> </jaxrs:serviceBeans> <jaxrs:providers> <ref bean="jsonProvider"/> </jaxrs:providers> <jaxrs:extensionMappings> <entry key="json" value="application/json"/> <entry key="xml" value="application/xml"/> </jaxrs:extensionMappings> </jaxrs:server> </beans>?
arrayKeys、produceMediaTypes、consumeMediaTypes分别映射的jsonKeys和jsonTypes分别是什么啊?因为我这样配置后启动报错:
2012-6-4 18:42:14 org.springframework.web.context.ContextLoader initWebApplicationContext
严重: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jsonProvider' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'jsonKeys' while setting bean property 'arrayKeys'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'jsonKeys' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
cxf版本是2.6.0
jaxb版本是2.2.5
spring版本是3.0
1.<util:list id="jsonKeys">
2. <value>Users</value>
3.</util:list>
4.
5.<util:list id="jsonTypes">
6. <value>application/json</value>
7. <value>application/jettison</value>
8.</util:list>
我的spring版本找不到util:list ,我改为了
<bean id="jsonKeys" class="java.util.ArrayList">
<constructor-arg>
<list>
<value>addresses</value>
</list>
</constructor-arg>
</bean>
效果为
{"helloWorld":{"@id":"123","addresses":{"addrID":2345,"name":"shenzhen"},"message":"Hello world rest and soap!!queryHello!--->queryHello00002"}}
HelloWorld属性的get方法上面加了@XmlAttribute
id是HelloWorld继承父类的属性,居然多了一个@符号,奇怪。addrID也还是没有引号,是不是我配置出问题了?
...
id是HelloWorld继承父类的属性,居然多了一个@符号,奇怪。addrID也还是没有引号,是不是我配置出问题了?
须加上上面配置文件中最关键的一句
<property name="attributesToElements" value="true"/>