我的问题类似于以下帖子: JSON ajax POST to Spring Portlet Controller @ResourceMapping conversion issue和@ResourceMapping that accepts JSON from Ajax request
我曾在那里尝试过Tipps,但没有成功。 我有以下技术:
在客户端,我生成一个字符串化的json-Object,其功能为jndo的kendo-ui,它在请求体中提交。目前它只包含一些filter-parameters(但它也可以包含服务器端分页,排序,分组等的附加参数。)。
在Firefox开发人员工具中,请求主体(有效负载)如下所示:
{
"filter" : {
"logic" : "and",
"filters" : [{
"field" : "name",
"value" : ""
}, {
"field" : "city",
"value" : ""
}, {
"field" : "zip",
"value" : ""
}, {
"field" : "country",
"value" : ""
}
]
}
}
在服务器端,我有一个用于该结构的POJO。我在 Spring Web MVC Servlet 环境中成功测试了这一点。使用 @RequestBody 和 Jackson ,JSON对象的反序列化可以正常工作。
在 liferay-portlet环境中工作我无法使用 @RequestBody 和 httpServletRequest 。
控制器如下所示:
@ResourceMapping(value = "test")
public void searchProviderTest(ResourceRequest request, ResourceResponse response,
@ModelAttribute("filter") DataSourceRequest dataSourceRequest) {
LOGGER.info(">>>>>> JsonOjekt per Parameter übergeben: " + request.getParameter("filter"));
LOGGER.info(">>>>>>>> DatasourceRequest: " + dataSourceRequest);
}
DataRequestObject 没有值。我看到了所有属性,但它们都是空的。并且没有请求参数“过滤器”(如预期的那样)
这是我的DataSourceRequest-Object(摘要):
public class DataSourceRequest {
private int page;
private int pageSize;
private int take;
private int skip;
private List<SortDescriptor> sort;
private List<GroupDescriptor> group;
private List<AggregateDescriptor> aggregate;
private HashMap<String, Object> data;
private FilterDescriptor filter;
public DataSourceRequest() {
filter = new FilterDescriptor();
data = new HashMap<String, Object>();
}
...(getters and setters)
public static class FilterDescriptor {
private String logic;
private List<FilterDescriptor> filters;
private String field;
private Object value;
private String operator;
private boolean ignoreCase = true;
public FilterDescriptor() {
filters = new ArrayList<FilterDescriptor>();
}
...(getters and setters)
我正在寻找一个解决方案,因为一些weecks,但我没有使用portlet-controller将JSON-Object转换(反序列化?)到DataSourceRequest-Object。我甚至不知道如何从portlet-controller访问请求体(有效负载)中的JSON-String。
在第二篇文章之后,嵌套对象可能是问题所在。我联系了kendo-ui支持的问题,我如何提交请求以获得帖子中描述的格式。但他们告诉我,这是不可能的(例如使用数据源对象的parameterMap-attribute),我必须在服务器端解决它。
第一篇文章描述了使用 @ModelAttribute 的解决方案,但后来我只获得了空对象 - 当我尝试使用@RequestParam获取JSON时,我得到了一个错误,该参数不在请求中(我认为因为它在正文中)
我正在考虑基于Spring Web MVC Servlet建立一个额外的RESTFul API - 我甚至试过它并且它有效 - 但我不确定这是否真的有意义,因为liferay已经有一个RESTFul -API。
有没有办法将JSON对象转换为Portlet控制器内的JAVA对象?或我是否需要额外的API?
欢迎任何提示!!
答案 0 :(得分:3)
使用Liferay对Json进行序列化和反序列化时遇到了同样的问题。我的解决方案是将json作为参数发送到表单数据中。这样我就能用以下方法检索Json:
String paramJson = ParamUtil.getString(request, "myJson");
然后使用Gson api反序列化:
new Gson().fromJson(paramJson, MyPOJO.class);
你不会在Gson身上遇到这么多麻烦。 您还可以使用Gson在返回服务时序列化对象,这样可以避免Liferay没有正确序列化的嵌套对象问题。
此代码显示如何将Json作为请求体发送:
请求将由方法&#39; serveResource&#39;处理。在MVCPortlet中。
var portletUrl = Liferay.PortletURL.createResourceURL();
portletUrl.setPortletId(<portletId>);
portletUrl.setResourceId('publicar'); // Any identifier
var formData = new FormData();
formData.append(<portlet-namespace> + 'myJson', JSON.stringify(object));
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', callbackSuccess, false);
xhr.open('POST', urlPortlet);
xhr.send(formData);
答案 1 :(得分:1)
分享我的经验赫拉是步骤:
在JS中将contentType设置为 application / x-www-form-urlencoded 。这是kendo-ui的代码(在后台使用jQuery Ajax)
<kendo:dataSource-transport-parameterMap>
function parameterMap(options,type) {
if(type==="read"){
return "osdeFilter=" + encodeURIComponent(JSON.stringify(options));
} else {
return "osdeModels=" + encodeURIComponent(JSON.stringify(options.models));
}
}
</kendo:dataSource-transport-parameterMap>
获取参数,在我的情况下使用Jackson manualy反序列化JSON字符串
@ResourceMapping(value = "test")
public void searchProviderTest(ResourceRequest request, ResourceResponse response)
throws JsonParseException, JsonMappingException, IOException {
String osdeFilter = URLDecoder.decode(request.getParameter("osdeFilter"),"UTF-8");
LOGGER.info(">>>>>> JsonOjekt per Parameter übergeben: " + request.getParameter("osdeFilter"));
ObjectMapper objectMapper = new ObjectMapper();
DataSourceRequest dataSourceRequest = objectMapper.readValue(osdeFilter, DataSourceRequest.class);
LOGGER.info(">>>>>>>> DatasourceRequest: " + dataSourceRequest);
}
与@giovani不同我不需要提交portlet-namespace。为此,您必须将以下配置添加到 liferay-portlet.xml
<requires-namespaced-parameters>false</requires-namespaced-parameters>