diff --git a/src/main/java/io/jboot/web/json/JbootJson.java b/src/main/java/io/jboot/web/json/JbootJson.java
index 5bd8a93a5273479dfc3ba72687d3bc80a1c35f3d..7b5067733b732555723bc2702c79e3a84e53121a 100644
--- a/src/main/java/io/jboot/web/json/JbootJson.java
+++ b/src/main/java/io/jboot/web/json/JbootJson.java
@@ -1,213 +1,213 @@
-/**
- * Copyright (c) 2015-2021, Michael Yang 杨福海 (fuhai999@gmail.com).
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.jboot.web.json;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.annotation.JSONField;
-import com.jfinal.json.JFinalJson;
-import com.jfinal.json.JFinalJsonKit;
-import com.jfinal.kit.LogKit;
-import com.jfinal.kit.StrKit;
-import com.jfinal.plugin.activerecord.CPI;
-import com.jfinal.plugin.activerecord.Model;
-import io.jboot.Jboot;
-import io.jboot.utils.ClassUtil;
-import io.jboot.utils.StrUtil;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.*;
-
-
-public class JbootJson extends JFinalJson {
-
- private JbootJsonConfig config = Jboot.config(JbootJsonConfig.class);
- protected static Map, MethodsAndFieldsWrapper> methodAndFieldsCache = new HashMap<>();
-
- public JbootJson() {
-
- //跳过 null 值输出到浏览器,提高传输性能
- setSkipNullValueField(config.isSkipNullValueField());
-
- //设置转换层级
- setConvertDepth(8);
-
- //默认设置为 CamelCase 的属性模式
- if (config.isCamelCaseJsonStyleEnable()) {
- setModelAndRecordFieldNameConverter((fieldName) -> StrKit.toCamelCase(fieldName, config.isCamelCaseToLowerCaseAnyway()));
- }
-
- setToJsonFactory(o -> o instanceof Model ? jbootModelToJson : null);
-
- if (StrUtil.isNotBlank(config.getTimestampPattern())) {
- setTimestampPattern(config.getTimestampPattern());
- }
- }
-
-
- protected JFinalJsonKit.ToJson> jbootModelToJson = (model, depth, ret) -> {
- if (JFinalJsonKit.checkDepth(depth--, ret)) {
- return;
- }
-
- Map map = new HashMap<>();
-
- if (!config.isSkipModelAttrs()) {
- fillModelAttrsToMap(CPI.getAttrs(model), map);
- }
-
- if (!config.isSkipBeanGetters()) {
- fillBeanToMap(model, map);
- }
-
- optimizeMapAttrs(map);
-
- JFinalJsonKit.mapToJson(map, depth, ret);
- };
-
-
- protected void fillModelAttrsToMap(Map attrs, Map toMap) {
- if (attrs != null && !attrs.isEmpty()) {
- for (Map.Entry entry : attrs.entrySet()) {
- String fieldName = entry.getKey();
- if (config.isCamelCaseJsonStyleEnable()) {
- fieldName = StrKit.toCamelCase(fieldName, config.isCamelCaseToLowerCaseAnyway());
- }
- toMap.put(fieldName, entry.getValue());
- }
- }
- }
-
-
- protected void fillBeanToMap(Object bean, Map toMap) {
-
- MethodsAndFieldsWrapper wrapper = methodAndFieldsCache.get(bean.getClass());
- if (wrapper == null) {
- synchronized (this) {
- if (wrapper == null) {
- wrapper = new MethodsAndFieldsWrapper(bean.getClass());
- } else {
- wrapper = methodAndFieldsCache.get(bean.getClass());
- }
- }
- }
-
- for (String ignoreField : wrapper.ignoreFields) {
- toMap.remove(ignoreField);
- }
-
-
- for (int i = 0; i < wrapper.fields.size(); i++) {
- String originalField = wrapper.originalFields.get(i);
- toMap.remove(originalField);
-
- Object value = invokeMethod(wrapper.methods.get(i), bean);
- String field = wrapper.fields.get(i);
- toMap.put(field, value);
- }
-
- }
-
-
- protected void optimizeMapAttrs(Map map) {
- }
-
- protected Object invokeMethod(Method method, Object bean) {
- try {
- return method.invoke(bean);
- } catch (Exception ex) {
- LogKit.error("can not invoke method: " + ClassUtil.buildMethodString(method), ex);
- return null;
- }
- }
-
-
- @Override
- public T parse(String jsonString, Class type) {
- return JSON.parseObject(jsonString, type);
- }
-
-
- public static class MethodsAndFieldsWrapper {
-
-
- private static boolean hasFastJson = ClassUtil.hasClass("com.alibaba.fastjson.JSON");
-
- private List fields = new LinkedList<>();
- private List methods = new LinkedList<>();
- private List originalFields = new LinkedList<>();
-
- //需要忽略的字段
- private List ignoreFields = new ArrayList<>();
-
- public MethodsAndFieldsWrapper(Class reflectiveClass) {
-
- Method[] methodArray = reflectiveClass.getMethods();
- for (Method method : methodArray) {
- if (method.getParameterCount() != 0
- || method.getReturnType() == void.class
- || !Modifier.isPublic(method.getModifiers())
- || "getClass".equals(method.getName())) {
- continue;
- }
-
-
- String fieldName = getGetterMethodField(method.getName());
- if (fieldName != null) {
- String attrName = StrKit.firstCharToLowerCase(fieldName);
- if (isIgnoreFiled(method)) {
- ignoreFields.add(attrName);
- } else {
- originalFields.add(attrName);
- fields.add(getDefineName(method, attrName));
- methods.add(method);
- }
- }
-
- }
- }
-
- private String getGetterMethodField(String methodName) {
- if (methodName.startsWith("get") && methodName.length() > 3) {
- return methodName.substring(3);
- } else if (methodName.startsWith("is") && methodName.length() > 2) {
- return methodName.substring(2);
- }
- return null;
- }
-
-
- private String getDefineName(Method method, String orginalName) {
- if (hasFastJson) {
- JSONField jsonField = method.getAnnotation(JSONField.class);
- if (jsonField != null && StrUtil.isNotBlank(jsonField.name())) {
- return jsonField.name();
- }
- }
- return orginalName;
- }
-
- private boolean isIgnoreFiled(Method method) {
- if (hasFastJson) {
- JSONField jsonField = method.getAnnotation(JSONField.class);
- if (jsonField != null && !jsonField.serialize()) {
- return true;
- }
- }
- return method.getAnnotation(JsonIgnore.class) != null;
- }
- }
-}
+/**
+ * Copyright (c) 2015-2021, Michael Yang 杨福海 (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.jboot.web.json;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.annotation.JSONField;
+import com.jfinal.json.JFinalJson;
+import com.jfinal.json.JFinalJsonKit;
+import com.jfinal.kit.LogKit;
+import com.jfinal.kit.StrKit;
+import com.jfinal.plugin.activerecord.CPI;
+import com.jfinal.plugin.activerecord.Model;
+import io.jboot.Jboot;
+import io.jboot.utils.ClassUtil;
+import io.jboot.utils.StrUtil;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+
+public class JbootJson extends JFinalJson {
+
+ private JbootJsonConfig config = Jboot.config(JbootJsonConfig.class);
+ protected static Map, MethodsAndFieldsWrapper> methodAndFieldsCache = new HashMap<>();
+
+ public JbootJson() {
+
+ //跳过 null 值输出到浏览器,提高传输性能
+ setSkipNullValueField(config.isSkipNullValueField());
+
+ //设置转换层级
+ setConvertDepth(config.getDepth());
+
+ //默认设置为 CamelCase 的属性模式
+ if (config.isCamelCaseJsonStyleEnable()) {
+ setModelAndRecordFieldNameConverter((fieldName) -> StrKit.toCamelCase(fieldName, config.isCamelCaseToLowerCaseAnyway()));
+ }
+
+ setToJsonFactory(o -> o instanceof Model ? jbootModelToJson : null);
+
+ if (StrUtil.isNotBlank(config.getTimestampPattern())) {
+ setTimestampPattern(config.getTimestampPattern());
+ }
+ }
+
+
+ protected JFinalJsonKit.ToJson> jbootModelToJson = (model, depth, ret) -> {
+ if (JFinalJsonKit.checkDepth(depth--, ret)) {
+ return;
+ }
+
+ Map map = new HashMap<>();
+
+ if (!config.isSkipModelAttrs()) {
+ fillModelAttrsToMap(CPI.getAttrs(model), map);
+ }
+
+ if (!config.isSkipBeanGetters()) {
+ fillBeanToMap(model, map);
+ }
+
+ optimizeMapAttrs(map);
+
+ JFinalJsonKit.mapToJson(map, depth, ret);
+ };
+
+
+ protected void fillModelAttrsToMap(Map attrs, Map toMap) {
+ if (attrs != null && !attrs.isEmpty()) {
+ for (Map.Entry entry : attrs.entrySet()) {
+ String fieldName = entry.getKey();
+ if (config.isCamelCaseJsonStyleEnable()) {
+ fieldName = StrKit.toCamelCase(fieldName, config.isCamelCaseToLowerCaseAnyway());
+ }
+ toMap.put(fieldName, entry.getValue());
+ }
+ }
+ }
+
+
+ protected void fillBeanToMap(Object bean, Map toMap) {
+
+ MethodsAndFieldsWrapper wrapper = methodAndFieldsCache.get(bean.getClass());
+ if (wrapper == null) {
+ synchronized (this) {
+ if (wrapper == null) {
+ wrapper = new MethodsAndFieldsWrapper(bean.getClass());
+ } else {
+ wrapper = methodAndFieldsCache.get(bean.getClass());
+ }
+ }
+ }
+
+ for (String ignoreField : wrapper.ignoreFields) {
+ toMap.remove(ignoreField);
+ }
+
+
+ for (int i = 0; i < wrapper.fields.size(); i++) {
+ String originalField = wrapper.originalFields.get(i);
+ toMap.remove(originalField);
+
+ Object value = invokeMethod(wrapper.methods.get(i), bean);
+ String field = wrapper.fields.get(i);
+ toMap.put(field, value);
+ }
+
+ }
+
+
+ protected void optimizeMapAttrs(Map map) {
+ }
+
+ protected Object invokeMethod(Method method, Object bean) {
+ try {
+ return method.invoke(bean);
+ } catch (Exception ex) {
+ LogKit.error("can not invoke method: " + ClassUtil.buildMethodString(method), ex);
+ return null;
+ }
+ }
+
+
+ @Override
+ public T parse(String jsonString, Class type) {
+ return JSON.parseObject(jsonString, type);
+ }
+
+
+ public static class MethodsAndFieldsWrapper {
+
+
+ private static boolean hasFastJson = ClassUtil.hasClass("com.alibaba.fastjson.JSON");
+
+ private List fields = new LinkedList<>();
+ private List methods = new LinkedList<>();
+ private List originalFields = new LinkedList<>();
+
+ //需要忽略的字段
+ private List ignoreFields = new ArrayList<>();
+
+ public MethodsAndFieldsWrapper(Class reflectiveClass) {
+
+ Method[] methodArray = reflectiveClass.getMethods();
+ for (Method method : methodArray) {
+ if (method.getParameterCount() != 0
+ || method.getReturnType() == void.class
+ || !Modifier.isPublic(method.getModifiers())
+ || "getClass".equals(method.getName())) {
+ continue;
+ }
+
+
+ String fieldName = getGetterMethodField(method.getName());
+ if (fieldName != null) {
+ String attrName = StrKit.firstCharToLowerCase(fieldName);
+ if (isIgnoreFiled(method)) {
+ ignoreFields.add(attrName);
+ } else {
+ originalFields.add(attrName);
+ fields.add(getDefineName(method, attrName));
+ methods.add(method);
+ }
+ }
+
+ }
+ }
+
+ private String getGetterMethodField(String methodName) {
+ if (methodName.startsWith("get") && methodName.length() > 3) {
+ return methodName.substring(3);
+ } else if (methodName.startsWith("is") && methodName.length() > 2) {
+ return methodName.substring(2);
+ }
+ return null;
+ }
+
+
+ private String getDefineName(Method method, String orginalName) {
+ if (hasFastJson) {
+ JSONField jsonField = method.getAnnotation(JSONField.class);
+ if (jsonField != null && StrUtil.isNotBlank(jsonField.name())) {
+ return jsonField.name();
+ }
+ }
+ return orginalName;
+ }
+
+ private boolean isIgnoreFiled(Method method) {
+ if (hasFastJson) {
+ JSONField jsonField = method.getAnnotation(JSONField.class);
+ if (jsonField != null && !jsonField.serialize()) {
+ return true;
+ }
+ }
+ return method.getAnnotation(JsonIgnore.class) != null;
+ }
+ }
+}
diff --git a/src/main/java/io/jboot/web/json/JbootJsonConfig.java b/src/main/java/io/jboot/web/json/JbootJsonConfig.java
index 521f5d799ebbe2bd478e2893466caa2911512892..9c137e18f7a1f6377a127f61c2a325f8a6868199 100644
--- a/src/main/java/io/jboot/web/json/JbootJsonConfig.java
+++ b/src/main/java/io/jboot/web/json/JbootJsonConfig.java
@@ -1,81 +1,90 @@
-/**
- * Copyright (c) 2015-2021, Michael Yang 杨福海 (fuhai999@gmail.com).
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.jboot.web.json;
-
-import io.jboot.app.config.annotation.ConfigModel;
-
-/**
- * @author Michael Yang 杨福海 (fuhai999@gmail.com)
- * @version V1.0
- */
-@ConfigModel(prefix = "jboot.json")
-public class JbootJsonConfig {
-
- private boolean camelCaseJsonStyleEnable = true;
- private boolean camelCaseToLowerCaseAnyway = false;
- private boolean skipNullValueField = true;
- private boolean skipModelAttrs = false;
- private boolean skipBeanGetters = false;
- private String timestampPattern;
-
- public boolean isCamelCaseJsonStyleEnable() {
- return camelCaseJsonStyleEnable;
- }
-
- public void setCamelCaseJsonStyleEnable(boolean camelCaseJsonStyleEnable) {
- this.camelCaseJsonStyleEnable = camelCaseJsonStyleEnable;
- }
-
- public boolean isCamelCaseToLowerCaseAnyway() {
- return camelCaseToLowerCaseAnyway;
- }
-
- public void setCamelCaseToLowerCaseAnyway(boolean camelCaseToLowerCaseAnyway) {
- this.camelCaseToLowerCaseAnyway = camelCaseToLowerCaseAnyway;
- }
-
- public boolean isSkipNullValueField() {
- return skipNullValueField;
- }
-
- public void setSkipNullValueField(boolean skipNullValueField) {
- this.skipNullValueField = skipNullValueField;
- }
-
- public boolean isSkipModelAttrs() {
- return skipModelAttrs;
- }
-
- public void setSkipModelAttrs(boolean skipModelAttrs) {
- this.skipModelAttrs = skipModelAttrs;
- }
-
- public boolean isSkipBeanGetters() {
- return skipBeanGetters;
- }
-
- public void setSkipBeanGetters(boolean skipBeanGetters) {
- this.skipBeanGetters = skipBeanGetters;
- }
-
- public String getTimestampPattern() {
- return timestampPattern;
- }
-
- public void setTimestampPattern(String timestampPattern) {
- this.timestampPattern = timestampPattern;
- }
-}
+/**
+ * Copyright (c) 2015-2021, Michael Yang 杨福海 (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.jboot.web.json;
+
+import io.jboot.app.config.annotation.ConfigModel;
+
+/**
+ * @author Michael Yang 杨福海 (fuhai999@gmail.com)
+ * @version V1.0
+ */
+@ConfigModel(prefix = "jboot.json")
+public class JbootJsonConfig {
+
+ private boolean camelCaseJsonStyleEnable = true;
+ private boolean camelCaseToLowerCaseAnyway = false;
+ private boolean skipNullValueField = true;
+ private boolean skipModelAttrs = false;
+ private boolean skipBeanGetters = false;
+ private String timestampPattern;
+ private int depth = 16;
+
+ public boolean isCamelCaseJsonStyleEnable() {
+ return camelCaseJsonStyleEnable;
+ }
+
+ public void setCamelCaseJsonStyleEnable(boolean camelCaseJsonStyleEnable) {
+ this.camelCaseJsonStyleEnable = camelCaseJsonStyleEnable;
+ }
+
+ public boolean isCamelCaseToLowerCaseAnyway() {
+ return camelCaseToLowerCaseAnyway;
+ }
+
+ public void setCamelCaseToLowerCaseAnyway(boolean camelCaseToLowerCaseAnyway) {
+ this.camelCaseToLowerCaseAnyway = camelCaseToLowerCaseAnyway;
+ }
+
+ public boolean isSkipNullValueField() {
+ return skipNullValueField;
+ }
+
+ public void setSkipNullValueField(boolean skipNullValueField) {
+ this.skipNullValueField = skipNullValueField;
+ }
+
+ public boolean isSkipModelAttrs() {
+ return skipModelAttrs;
+ }
+
+ public void setSkipModelAttrs(boolean skipModelAttrs) {
+ this.skipModelAttrs = skipModelAttrs;
+ }
+
+ public boolean isSkipBeanGetters() {
+ return skipBeanGetters;
+ }
+
+ public void setSkipBeanGetters(boolean skipBeanGetters) {
+ this.skipBeanGetters = skipBeanGetters;
+ }
+
+ public String getTimestampPattern() {
+ return timestampPattern;
+ }
+
+ public void setTimestampPattern(String timestampPattern) {
+ this.timestampPattern = timestampPattern;
+ }
+
+ public int getDepth() {
+ return depth;
+ }
+
+ public void setDepth(int depth) {
+ this.depth = depth;
+ }
+}