renderJson是怎么完成Json序列化并返回的?

程序代码,renderJson之后,程序结束,并返回json,http响应

public void listData() {

Page<UserAppointment> page = srv.paginate(getParaToInt("pageNo", 1));

ServiceBizKit.fillUserAppointment(page);

PageInfo<UserAppointment> pageInfo = WebKit.convertPage(page);

Result result = WebKit.buildDataResult(pageInfo);

renderJson(result);

}


源码,就返回了1个render对象

public void renderJson(Object object) {

render = object instanceof JsonRender ? (JsonRender)object : renderManager.getRenderFactory().getJsonRender(object);

}


序列化是怎么执行的了?

序列化后的json串,没有看到HTTP响应代码呢?比如 response.write("JFinal").


----------------------

分析这个是自己有个 个性化扩展类的需求。

Post等对象都有自己的 枚举属性,比如 频道(1、2、3)。

如果是普通代码,自己写1个get方法,序列化的时候,自动会多1个属性。

但是JFinal序列化不是根据get方法,而是attrs属性,因此 定义了1个接口,

让 Model实现,并 调用这个方法。

super.put("channelName", ChannelEnum.getNameByCode(channel));

ajax代码,返回后直接使用 channelName中文字符串。


现在不想手动调用。

凡是序列化都会 执行renderJson等json序列化方法。

找到这个 统一的入口,扩展下,

if( 我的模型等对象 实现了FillProperty 接口){

       model.fillExtendProperty();

}

简而言之,想增加1个 json序列化的 回调方法,“钩子”。


@SuppressWarnings("serial")

public class Post extends BasePost<Post> implements FillProperty {


public PostCategory getPostCategory() {

return super.get("postCategory");

}


public void setPostCategory(PostCategory postCategory) {

super.put("postCategory", postCategory);

}


public void fillExtendProperty() {

Integer channel = super.getChannel();

super.put("channelName", ChannelEnum.getNameByCode(channel));


}

}


评论区

fansunion

2018-09-05 08:40

ActionHandler

Render render = controller.getRender();
if (render instanceof ForwardActionRender) {
String actionUrl = ((ForwardActionRender)render).getActionUrl();
if (target.equals(actionUrl)) {
throw new RuntimeException("The forward action url is the same as before.");
} else {
handle(actionUrl, request, response, isHandled);
}
return ;
}

if (render == null) {
render = renderManager.getRenderFactory().getDefaultRender(action.getViewPath() + action.getMethodName());
}
render.setContext(request, response, action.getViewPath()).render();

会调用JSONRender

public void render() {
if (jsonText == null) {
buildJsonText();
}

PrintWriter writer = null;
try {
response.setHeader("Pragma", "no-cache"); // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);

response.setContentType(forIE ? contentTypeForIE : contentType);
writer = response.getWriter();
writer.write(jsonText);
writer.flush();
} catch (IOException e) {
throw new RenderException(e);
}
}

fansunion

2018-09-05 08:41

代码简单,架构清晰 就是好啊。Spring等老外的都是一坨屎,一层套一层。

fansunion

2018-09-05 08:46

重写 JsonRender的buildJsonText方法。
序列化实际上是这个 this.jsonText = JsonKit.toJson(map);
public static String toJson(Object object) {
return Json.getJson().toJson(object);
}

重写JFianlJson等具体Json的
protected String toJson(Object value, int depth) {
if(value == null || (depth--) < 0)
return "null";

if(value instanceof String)
return "\"" + escape((String)value) + "\"";

if(value instanceof Double){
if(((Double)value).isInfinite() || ((Double)value).isNaN())
return "null";
else
return value.toString();
}

if(value instanceof Float){
if(((Float)value).isInfinite() || ((Float)value).isNaN())
return "null";
else
return value.toString();
}

fansunion

2018-09-05 09:50

解决方案:增加 json序列化时间通知

public void configConstant(Constants me) {
me.setJsonFactory(JtnMixedJsonFactory.me());
}

package com.jtn.jfinal.extend.json;

import com.jfinal.json.FastJson;
import com.jfinal.json.JFinalJson;
import com.jfinal.json.Json;
import com.jfinal.json.MixedJsonFactory;
import com.jtn.jfinal.extend.JsonEvent;
/**
* 扩展JFinal的MixedJsonFactory,实现Json序列化事件通知。
* @author fansunion
*
* 2018年9月5日
*/
public class JtnMixedJsonFactory extends MixedJsonFactory {
private static final JtnMixedJsonFactory me = new JtnMixedJsonFactory();

public static MixedJsonFactory me() {
return me;
}

private static MixedJson mixedJson = new MixedJson();

public Json getJson() {
return mixedJson;
}

private static class MixedJson extends Json {

private static JtnJFinalJson jFinalJson = JtnJFinalJson.getJson();
private static FastJson fastJson = FastJson.getJson();

public String toJson(Object object) {
return jFinalJson.toJson(object);
}

public T parse(String jsonString, Class type) {
return fastJson.parse(jsonString, type);
}
}

private static class JtnJFinalJson extends JFinalJson{

public static JtnJFinalJson getJson() {
return new JtnJFinalJson();
}

@Override
public String toJson(Object value, int depth) {
boolean instanceOfJsonEvent = value instanceof JsonEvent;
JsonEvent jsonEvent=null;
if(instanceOfJsonEvent){
jsonEvent=( JsonEvent)value;
}
//json序列化前,回调
if(jsonEvent != null){
jsonEvent.beforeToJson(value);
}
//json序列化
String json=super.toJson(value, depth);
//json序列化后,回调
if(jsonEvent != null){
((JsonEvent)value).afterToJson(json);
}
return json;
}
}
}

JFinal

2018-09-05 10:08

@fansunion jfinal 几乎所有功能都留了扩展的口子,而且扩展起来极其容易

扩展的方式也很多,例如你上面那个 json 扩展的需求,你还可以通过引入一个 BaseController 继承 Controller,在其中覆盖父类的 renderJson 方法,然后做个自己的 MyJsonRender,最后这样:
public void renderJson(..) {
this.render = new MyRender(...);
}

或者不引入 BaseController 也可以,像下面这么调用就好:
render(new MyJsonRender(...));

如果不想扩展的话,还可以直接使用 renderJson(String jsonString) 带 String参的这个,然后自己将 json 转完以后传进去

JFinal

2018-09-05 10:16

如果想在 spring 下面做点扩展,先绕个十万八千里,看懂它的代码再开始写代码,黄花菜都凉了

jfinal 的 enjoy 引擎中做了支持 spring 的 view 的括展,扩展它的 AbstractTemplateView,先是有七层继承关系,再来六个接口实现,光是看清它里面的各种依赖、协同关系就得费很多时间,更别说扩展了

这还不算,扩展 view 还得同时扩展 AbstractTemplateViewResolver,以来了六层继承关系和五个接口实现。这个 AbstractTemplateView、AbstractTemplateViewResolver 的设计者一定是脑子进屎了

fansunion

2018-09-05 11:00

逐步精通JFinal,尽可能不用Spring,今后自己当boss。(*^__^*)
render(new MyJsonRender(...)); 这个做法 也很不错。

fansunion

2018-09-05 11:11

JsonRender的jsonText是private,而且没有set方法,不方便 简单的重写额。
(感觉 有点坑 o(︶︿︶)o )

public class JtnJsonRender extends JsonRender{

public JtnJsonRender(Object object) {
super.jsonText = MyJsonKit.toJson(object);
}
}
只能重写render方法,或者copy源代码,大范围地重写代码才行。

renderJson(String jsonString)。这种比较灵活,就是和常见代码不太一致。
总之,还是看实际情况,怎么用着方便恰当就怎么用。
目前采用扩展 增加JsonEvent的方式。

方法的确多种多样。

JFinal

2018-09-05 11:30

@fansunion 刚刚已将 JsonRender 中的所有属性改成 protected, jfinal 3.5 就可以用上了

fansunion

2018-09-05 11:31

@JFinal 看来我立功了,哦也。

cs3230524

2019-10-14 19:58

你好!请问jsonEvent.beforeToJson(value);做了什么工作?

cs3230524

2019-10-14 19:58

实现可以看一下吗

热门反馈

扫码入社