Closed jay763190097 closed 3 months ago
@jay763190097 Can you provide a test case? The code sample should include a Controller interface and CommonRequest. You can include the test code in the issue.
@shalousun 就是文档里面的参数对象,其实现在用的很多,为了统一结构。 CommonRequest来自一个lib包
public class CommonRequest<T> {
private RequesterHeader header;
private transient T body;
}
/**
* customer creation api
* @param request com.abc.CustomerCreateDto
* @return
*
*/
@PostMapping("/customer/create")
public CommonResult<CustomerCreateResDto> create(@RequestBody @Valid CommonRequest<CustomerCreateDto> request) {
}
文档值生成了CommonRequest里面的header结构,body完全没有。。。加不加param都是这样的。 header能正常看到结构,证明不是外部源代码的问题。
@jay763190097 Fields modified by the transient keyword are ignored by smart-doc.
@shalousun The transient keyword, which is used for deserialization in the request body, makes sense, Because it will no longer be serialized. The idea is that even if it is serialized, it reduces the overhead of serialization, so it should be parsed. If it is in the response body, we should ignore it because this is a serialization operation.
@jay763190097 Let's first test different JSON serialization scenarios, and then make a fix based on the actual results.
@shalousun for serialization scenario, we use transient to ignore this field, that‘s right. But for de-serialization scenario, we should parse this filed.
@shalousun for serialization scenario, we use transient to ignore this field, that‘s right. But for de-serialization scenario, we should parse this filed.
Through testing, it has been found that the handling of fields modified with transient
varies across different JSON processing frameworks. In Jackson, such fields are not ignored by default, whereas in Fastjson, they are ignored. As a result, the community has had to provide a separate configuration option to determine whether fields marked with transient
should be included or not.
transient
Fields by Different JSON Serialization FrameworksDifferent JSON serialization frameworks handle transient
fields in various ways. The following code demonstrates these differences:
package com.power.doc.model;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class TestTransient implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* name
*/
private String name;
/**
* password
*/
private transient String password;
@Override
public String toString() {
return "TestTransient{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
package com.power.doc.utils;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.power.doc.model.TestTransient;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* json transient test
*/
public class JsonTransientTest {
/**
* Test Json transient filed
*/
@DisplayName("Test Json transient filed")
@Test
public void test() throws JsonProcessingException {
TestTransient testTransient = new TestTransient();
testTransient.setName("test");
testTransient.setPassword("123456");
ObjectMapper objectMapper = new ObjectMapper();
System.out.println("com.alibaba.fastjson.JSON:" + com.alibaba.fastjson.JSON.toJSON(testTransient));
System.out.println("com.alibaba.fastjson2.JSON:" + JSON.toJSON(testTransient));
System.out.println("com.fasterxml.jackson.databind.ObjectMapper:" + objectMapper.writeValueAsString(testTransient));
System.out.println("com.google.gson.Gson:" + new Gson().toJson(testTransient));
// com.alibaba.fastjson.JSON:{"password":"123456","name":"test"}
// com.alibaba.fastjson2.JSON:{"name":"test"}
// com.fasterxml.jackson.databind.ObjectMapper:{"name":"test","password":"123456"}
// com.google.gson.Gson:{"name":"test"}
System.out.println();
String test = "{\"password\":\"123456\",\"name\":\"test\"}";
System.out.println("com.alibaba.fastjson.JSON:" + com.alibaba.fastjson.JSON.parseObject(test, TestTransient.class));
System.out.println("com.alibaba.fastjson2.JSON:" + JSON.parseObject(test, TestTransient.class));
System.out.println("com.fasterxml.jackson.databind.ObjectMapper:" + objectMapper.readValue(test, TestTransient.class));
System.out.println("com.google.gson.Gson:" + new Gson().fromJson(test, TestTransient.class));
// com.alibaba.fastjson.JSON:TestTransient{name='test', password='123456'}
// com.alibaba.fastjson2.JSON:TestTransient{name='test', password='123456'}
// com.fasterxml.jackson.databind.ObjectMapper:TestTransient{name='test', password='123456'}
// com.google.gson.Gson:TestTransient{name='test', password='null'}
}
}
Analysis of Results:
Serialization:
com.alibaba.fastjson.JSON
and com.fasterxml.jackson.databind.ObjectMapper
include the transient
field during serialization, producing {"name":"test","password":"123456"}
.com.alibaba.fastjson2.JSON
and com.google.gson.Gson
exclude the transient
field during serialization, resulting in {"name":"test"}
.Deserialization:
com.alibaba.fastjson.JSON
, com.alibaba.fastjson2.JSON
, and com.fasterxml.jackson.databind.ObjectMapper
successfully deserialize the transient
field, producing TestTransient{name='test', password='123456'}
.com.google.gson.Gson
does not deserialize the transient
field, resulting in TestTransient{name='test', password='null'}
.Conclusion:
The handling of transient
fields varies among different JSON frameworks. Below is a summary table that illustrates these differences:
Framework | Serialization (Includes transient field) |
Deserialization (Restores transient field) |
---|---|---|
com.alibaba.fastjson.JSON | Yes | Yes |
com.alibaba.fastjson2.JSON | No | Yes |
com.fasterxml.jackson.databind.ObjectMapper | Yes | Yes |
com.google.gson.Gson | No | No |
transient
field during JSON serialization.transient
field during JSON deserialization.This table highlights that Fastjson
(original version) and Jackson
include transient
fields in both serialization and deserialization. Fastjson2
excludes the transient
field during serialization but correctly restores it during deserialization. Gson
, on the other hand, excludes the transient
field in both serialization and deserialization processes.
@jay763190097 For versions after 3.0.8, you can configure the serialization of fields marked with transients
: reference configuration options:
{
"serializeRequestTransients": true,
"serializeResponseTransients": false
}
@shalousun @linwumingshi After checking the source code, I found a config property skipTransientField, the default value is true. I added this property and changed it to false, then It worked for me, didn't sync with you guys, my bad. Is it a duplicate property you are defined?
@shalousun @linwumingshi Thanks all, I checked the PR, you already considered the old config property, Cool !!!, I'll use the property serializeRequestTransients.
Contact Details
jiangmang.1992@163.com
Version
3.0.7
Plugin
smart-doc-maven-plugin
Build tool version
maven 3.6.2
Jdk version
17
Describe the bug (Bug描述,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)
My request object is CommonRequest, which has two properties, header and body, Where the body is a generic wrapper object. I used generics on the requested api interface, specifying the type of body. But there is no structure on the document to generate the body.
Expected Behavior (您期望的结果,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)
Expected to support wrapper classes as request parameters and return results
Current Behavior (当前结果,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)
Structure has only header, no body
Steps to Reproduce (Bug产生步骤,请尽量提供用例代码。社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)
With this wrapper class,
you can reproduce the problem.
Possible Solution (Bug解决建议,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)
No response
Context (Bug影响描述,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)
No response
Validations