Skip to content
This repository was archived by the owner on Dec 4, 2025. It is now read-only.

Commit 73c89ac

Browse files
authored
Merge pull request #875 from linwumingshi/feature/json-view
feat: ✨ Add support for `@JsonView`
2 parents c62f935 + f72c701 commit 73c89ac

13 files changed

Lines changed: 427 additions & 116 deletions

src/main/java/com/ly/doc/builder/IBaseDocBuilderTemplate.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,16 @@ public interface IBaseDocBuilderTemplate<T extends IDoc> {
6868

6969
/**
7070
* get all doc api data
71+
* @param isAsciidoc is Asciidoc
72+
* @param showJavaType show java type
73+
* @param paramsDataToTree params data to tree
7174
* @param config ApiConfig
7275
* @param javaProjectBuilder JavaProjectBuilder
7376
* @return ApiAllData
7477
*/
75-
default List<T> getApiDoc(boolean adoc, boolean showJavaType, boolean paramsDataToTree, ApiConfig config,
78+
default List<T> getApiDoc(boolean isAsciidoc, boolean showJavaType, boolean paramsDataToTree, ApiConfig config,
7679
JavaProjectBuilder javaProjectBuilder) {
77-
config.setAdoc(adoc);
80+
config.setAdoc(isAsciidoc);
7881
config.setShowJavaType(showJavaType);
7982
config.setParamsDataToTree(paramsDataToTree);
8083
this.checkAndInit(config, Boolean.TRUE);

src/main/java/com/ly/doc/builder/websocket/WebSocketDocBuilderTemplate.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ public class WebSocketDocBuilderTemplate implements IBaseDocBuilderTemplate<WebS
5454

5555
/**
5656
* get all websocket api data.
57-
* @param adoc is adoc
57+
* @param isAsciidoc is Asciidoc
5858
* @param config ApiConfig
5959
* @param javaProjectBuilder JavaProjectBuilder
6060
* @return ApiAllData
6161
*/
62-
public List<WebSocketDoc> getWebSocketApiDoc(boolean adoc, ApiConfig config,
62+
public List<WebSocketDoc> getWebSocketApiDoc(boolean isAsciidoc, ApiConfig config,
6363
JavaProjectBuilder javaProjectBuilder) {
64-
config.setAdoc(adoc);
64+
config.setAdoc(isAsciidoc);
6565
this.checkAndInit(config, Boolean.TRUE);
6666
config.setParamsDataToTree(false);
6767
config
@@ -89,6 +89,7 @@ public List<WebSocketDoc> getWebSocketApiDoc(ApiConfig config, JavaProjectBuilde
8989
* Merge all websocket api doc into one document.
9090
* @param webSocketDocList list data of Api doc
9191
* @param config api config
92+
* @param javaProjectBuilder JavaProjectBuilder
9293
* @param template template
9394
* @param outPutFileName output file
9495
*/

src/main/java/com/ly/doc/constants/DocAnnotationConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ public interface DocAnnotationConstants {
3838
*/
3939
String SHORT_JSON_IGNORE_PROPERTIES = "JsonIgnoreProperties";
4040

41+
/**
42+
* jackson JsonView annotation {@code com.fasterxml.jackson.annotation.JsonView}
43+
*/
44+
String SHORT_JSON_VIEW = "JsonView";
45+
4146
/**
4247
* jackson JsonProperty annotation
4348
* {@code com.fasterxml.jackson.annotation.JsonProperty}

src/main/java/com/ly/doc/helper/JsonBuildHelper.java

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.power.common.util.CollectionUtil;
2828
import com.power.common.util.StringUtil;
2929
import com.thoughtworks.qdox.model.*;
30+
import com.thoughtworks.qdox.model.expression.AnnotationValue;
3031

3132
import java.util.*;
3233

@@ -95,8 +96,8 @@ public static String buildReturnJson(DocJavaMethod docJavaMethod, ProjectDocConf
9596
return StringUtil.removeQuotes(DocUtil.jsonValueByType(typeName));
9697
}
9798

98-
return JsonUtil.toPrettyFormat(
99-
buildJson(typeName, returnType, Boolean.TRUE, 0, new HashMap<>(16), new HashSet<>(0), builder));
99+
return JsonUtil.toPrettyFormat(buildJson(typeName, returnType, Boolean.TRUE, 0, new HashMap<>(16),
100+
Collections.emptySet(), docJavaMethod.getJsonViewClasses(), builder));
100101
}
101102

102103
/**
@@ -107,11 +108,14 @@ public static String buildReturnJson(DocJavaMethod docJavaMethod, ProjectDocConf
107108
* @param counter The recursion counter.
108109
* @param registryClasses A map to keep track of processed classes.
109110
* @param groupClasses A set of valid group classes.
111+
* @param methodJsonViewClasses A set of valid `@JsonView` classes on controller
112+
* method.
110113
* @param builder The project config builder.
111114
* @return The JSON string representation of the type.
112115
*/
113116
public static String buildJson(String typeName, String genericCanonicalName, boolean isResp, int counter,
114-
Map<String, String> registryClasses, Set<String> groupClasses, ProjectDocConfigBuilder builder) {
117+
Map<String, String> registryClasses, Set<String> groupClasses, Set<String> methodJsonViewClasses,
118+
ProjectDocConfigBuilder builder) {
115119

116120
Map<String, String> genericMap = new HashMap<>(10);
117121
JavaClass javaClass = builder.getJavaProjectBuilder().getClassByName(typeName);
@@ -187,14 +191,16 @@ else if (JavaClassValidateUtil.isPrimitive(gName)) {
187191
}
188192
else if (gName.contains("<")) {
189193
String simple = DocClassUtil.getSimpleName(gName);
190-
String json = buildJson(simple, gName, isResp, nextLevel, registryClasses, groupClasses, builder);
194+
String json = buildJson(simple, gName, isResp, nextLevel, registryClasses, groupClasses,
195+
methodJsonViewClasses, builder);
191196
data.append(json);
192197
}
193198
else if (JavaClassValidateUtil.isCollection(gName)) {
194199
data.append("\"any object\"");
195200
}
196201
else {
197-
String json = buildJson(gName, gName, isResp, nextLevel, registryClasses, groupClasses, builder);
202+
String json = buildJson(gName, gName, isResp, nextLevel, registryClasses, groupClasses,
203+
methodJsonViewClasses, builder);
198204
data.append(json);
199205
}
200206
data.append("]");
@@ -228,7 +234,8 @@ else if (JavaClassValidateUtil.isPrimitive(gicName)) {
228234
}
229235
else if (gicName.contains("<")) {
230236
String simple = DocClassUtil.getSimpleName(gicName);
231-
String json = buildJson(simple, gicName, isResp, nextLevel, registryClasses, groupClasses, builder);
237+
String json = buildJson(simple, gicName, isResp, nextLevel, registryClasses, groupClasses,
238+
methodJsonViewClasses, builder);
232239
data.append("{").append("\"mapKey\":").append(json).append("}");
233240
}
234241
else {
@@ -239,7 +246,7 @@ else if (gicName.contains("<")) {
239246
.append(field.getName())
240247
.append("\":")
241248
.append(buildJson(gicName, genericCanonicalName, isResp, counter + 1, registryClasses,
242-
groupClasses, builder))
249+
groupClasses, methodJsonViewClasses, builder))
243250
.append(",");
244251
}
245252
// Remove the trailing comma
@@ -252,7 +259,7 @@ else if (gicName.contains("<")) {
252259
data.append("{")
253260
.append("\"mapKey\":")
254261
.append(buildJson(gicName, genericCanonicalName, isResp, counter + 1, registryClasses,
255-
groupClasses, builder))
262+
groupClasses, methodJsonViewClasses, builder))
256263
.append("}");
257264
}
258265
}
@@ -266,7 +273,8 @@ else if (JavaTypeConstants.JAVA_OBJECT_FULLY.equals(typeName)) {
266273
}
267274
// Handle Reactor types
268275
else if (JavaClassValidateUtil.isReactor(typeName)) {
269-
data.append(buildJson(globGicName[0], typeName, isResp, nextLevel, registryClasses, groupClasses, builder));
276+
data.append(buildJson(globGicName[0], typeName, isResp, nextLevel, registryClasses, groupClasses,
277+
methodJsonViewClasses, builder));
270278
return data.toString();
271279
}
272280
// Process fields of the class
@@ -306,8 +314,19 @@ else if (JavaClassValidateUtil.isReactor(typeName)) {
306314
String jsonFormatString = null;
307315
// has Annotation @JsonSerialize And using ToStringSerializer
308316
boolean toStringSerializer = false;
317+
// Handle @JsonView; if the field is not annotated with @JsonView, skip
318+
// it.
319+
if (!methodJsonViewClasses.isEmpty() && isResp && annotations.isEmpty()) {
320+
continue;
321+
}
309322
// Handle annotations on the field
310323
for (JavaAnnotation annotation : annotations) {
324+
// Handle @JsonView
325+
if (JavaClassUtil.shouldExcludeFieldFromJsonView(annotation, methodJsonViewClasses, isResp,
326+
builder)) {
327+
continue out;
328+
}
329+
311330
String annotationName = annotation.getType().getValue();
312331
// if the field is annotated with @JsonSerialize
313332
if (DocAnnotationConstants.SHORT_JSON_SERIALIZE.equals(annotationName)
@@ -316,7 +335,7 @@ else if (JavaClassValidateUtil.isReactor(typeName)) {
316335
toStringSerializer = true;
317336
continue;
318337
}
319-
338+
// if the field is annotated with @Null And isResp is false
320339
if (JSRAnnotationConstants.NULL.equals(annotationName) && !isResp) {
321340
if (CollectionUtil.isEmpty(groupClasses)) {
322341
continue out;
@@ -346,16 +365,17 @@ else if (JavaClassValidateUtil.isReactor(typeName)) {
346365
// Handle @JsonProperty
347366
else if (DocAnnotationConstants.SHORT_JSON_PROPERTY.equals(annotationName)
348367
|| DocAnnotationConstants.GSON_ALIAS_NAME.equals(annotationName)) {
349-
if (null != annotation.getProperty(DocAnnotationConstants.VALUE_PROP)) {
350-
fieldName = StringUtil
351-
.removeQuotes(annotation.getProperty(DocAnnotationConstants.VALUE_PROP).toString());
368+
AnnotationValue annotationValue = annotation.getProperty(DocAnnotationConstants.VALUE_PROP);
369+
if (null != annotationValue) {
370+
fieldName = StringUtil.removeQuotes(annotationValue.toString());
352371
}
353372
}
354373
// Handle @JsonFormat
355374
else if (DocAnnotationConstants.JSON_FORMAT.equals(annotationName)) {
356375
jsonFormatString = DocUtil.getJsonFormatString(field, annotation);
357376
}
358377
}
378+
359379
String typeSimpleName = docField.getTypeSimpleName();
360380
String fieldGicName = docField.getTypeGenericCanonicalName();
361381
CustomField.Key key = CustomField.Key.create(docField.getDeclaringClassName(), fieldName);
@@ -450,7 +470,8 @@ else if (gicName.length() == 1) {
450470
if (!typeName.equals(gicName1)) {
451471
data0.append("[")
452472
.append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp,
453-
nextLevel, registryClasses, groupClasses, builder))
473+
nextLevel, registryClasses, groupClasses, methodJsonViewClasses,
474+
builder))
454475
.append("]")
455476
.append(",");
456477
}
@@ -475,7 +496,7 @@ else if (gicName.length() == 1) {
475496
fieldGicName = DocUtil.formatFieldTypeGicName(genericMap, fieldGicName);
476497
data0.append("[")
477498
.append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses,
478-
groupClasses, builder))
499+
groupClasses, methodJsonViewClasses, builder))
479500
.append("]")
480501
.append(",");
481502
}
@@ -517,7 +538,8 @@ else if (JavaClassValidateUtil.isMap(subTypeName)) {
517538
data0.append("{")
518539
.append("\"mapKey\":")
519540
.append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp,
520-
nextLevel, registryClasses, groupClasses, builder))
541+
nextLevel, registryClasses, groupClasses, methodJsonViewClasses,
542+
builder))
521543
.append("},");
522544
}
523545
else {
@@ -529,7 +551,7 @@ else if (JavaClassValidateUtil.isMap(subTypeName)) {
529551
data0.append("{")
530552
.append("\"mapKey\":")
531553
.append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses,
532-
groupClasses, builder))
554+
groupClasses, methodJsonViewClasses, builder))
533555
.append("},");
534556
}
535557
}
@@ -544,7 +566,7 @@ else if (fieldGicName.length() == 1) {
544566
String simple = DocClassUtil.getSimpleName(gicName);
545567
data0
546568
.append(buildJson(simple, gicName, isResp, nextLevel, registryClasses, groupClasses,
547-
builder))
569+
methodJsonViewClasses, builder))
548570
.append(",");
549571
}
550572
}
@@ -601,7 +623,7 @@ else if (StringUtil.isNotEmpty(jsonFormatString)) {
601623
fieldGicName = DocUtil.formatFieldTypeGicName(genericMap, fieldGicName);
602624
data0
603625
.append(buildJson(subTypeName, fieldGicName, isResp, nextLevel, registryClasses,
604-
groupClasses, builder))
626+
groupClasses, methodJsonViewClasses, builder))
605627
.append(",");
606628
}
607629
}

0 commit comments

Comments
 (0)