同时使用@JsonProperty和@ApiModelProperty时,在接口文档上属性名该是啥???

场景

由于想在接口文档上显示属性的描述,于是使用了如下代码

@JsonProperty(value = "aaBB")
@ApiModelProperty(value = "描述内容")
private Integer cc;

可是打开接口文档一看,原来的cc属性不见了,只剩下aaBB。

小白我只知道,@JsonProperty适用于序列化时转换的,@ApiModelProperty是为了接口文档展示使用的。两者这么说下来好像没什么关系啊。没想明白,心里有点堵。上网搜寻了好久,只发现别人有使用@JsonProperty来强制改变名字的需求,但是没有说明为啥可以这样。只能自己慢慢看看源码了…

swagger接口文档的内容总归来源于你的代码,所有的信息其实就是在AbstractApplicationContext 的refresh方法,有了雏形。

AbstractApplicationContext.refresh ->

EmbeddedWebApplicationContext.finishRefresh ->

AbstractApplicationContext.finishRefresh ->

DefaultLifecycleProcessor.onRefresh -> startBeans -> start -> doStart
->

DocumentationPluginsBootstrapper.start -> scanDocumentation

ApiDocumentationScanner.scan ->

ApiListingScanner.scan ->

ApiModelReader.read ->

… ->

BasicBeanDescription.findProperties ->

… ->

POJOPropertiesCollector.collectAll -> _addFields

上面记录的流程有点多,不用慌,只是为了更加清楚经过了哪些流程,不仅可以知道其来龙去脉,还能方便以后深入学习。今天就简单解决下遇到的问题,了解一下到底是哪一步导致的问题。

上述流程可以看出来,主要经历在onRefresh 里面触发了Api相关的读取操作。在收集model(实体类)的属性时,就已经和JsonProperty纠缠不清了。

collectAll
protected void collectAll()
{
    LinkedHashMap<String, POJOPropertyBuilder> props = new LinkedHashMap<String, POJOPropertyBuilder>();

    // 获取基本的属性,并且这里会记录每个属性可能有的别名
    _addFields(props);
    _addMethods(props);
    // 25-Jan-2016, tatu: Avoid introspecting (constructor-)creators for non-static
    //    inner classes, see [databind#1502]
    if (!_classDef.isNonStaticInnerClass()) {
        _addCreators(props);
    }
    _addInjectables(props);

......

    // 重命名属性,就是这里将结合基本属性信息与_addFields收集的别名信息
    _renameProperties(props);
......
}
_addFields
protected void _addFields(Map<String, POJOPropertyBuilder> props)
{
    ......
    // 遍历所有属性
    for (AnnotatedField f : _classDef.fields()) {
        // 获取字段基础名字(就是开头例子的 cc)
        String implName = ai.findImplicitPropertyName(f);
        // 记录有@JsonValue的字段
        if (Boolean.TRUE.equals(ai.hasAsValue(f))) {
            if (_jsonValueAccessors == null) {
                _jsonValueAccessors = new LinkedList<>();
            }
            _jsonValueAccessors.add(f);
            continue;
        }
        // 记录有@JsonAnySetter的字段
        if (Boolean.TRUE.equals(ai.hasAnySetter(f))) {
            if (_anySetterField == null) {
                _anySetterField = new LinkedList<AnnotatedMember>();
            }
            _anySetterField.add(f);
            continue;
        }
        if (implName == null) {
            implName = f.getName();
        }
        PropertyName pn;
        
        // 寻找序列化相关的名字
        if (_forSerialization) {
            /* 18-Aug-2011, tatu: As per existing unit tests, we should only
             *   use serialization annotation (@JsonSerialize) when serializing
             *   fields, and similarly for deserialize-only annotations... so
             *   no fallbacks in this particular case.
             */
            pn = ai.findNameForSerialization(f);
        } else {
            pn = ai.findNameForDeserialization(f);
        }
        boolean hasName = (pn != null);
        boolean nameExplicit = hasName;

        // 记录定义的别名
        if (nameExplicit && pn.isEmpty()) { // empty String meaning "use default name", here just means "same as field name"
            pn = _propNameFromSimple(implName);
            nameExplicit = false;
        }
       ......
        _property(props, implName).addField(f, pn, nameExplicit, visible, ignored);
    }
}
findNameForDeserialization
public PropertyName findNameForDeserialization(Annotated a)
{
    // @JsonSetter 优先级高于 @JsonProperty
    boolean useDefault = false;
    JsonSetter js = _findAnnotation(a, JsonSetter.class);
    if (js != null) {
        String s = js.value();
        // 04-May-2018, tatu: Need to allow for "nameless" `@JsonSetter` too
        if (s.isEmpty()) {
            useDefault = true;
        } else {
            return PropertyName.construct(s);
        }
    }
    JsonProperty pann = _findAnnotation(a, JsonProperty.class);
    // 找到JsonProperty的value作为逻辑名字
    if (pann != null) {
        return PropertyName.construct(pann.value());
    }
    if (useDefault || _hasOneOf(a, ANNOTATIONS_TO_INFER_DESER)) {
        return PropertyName.USE_DEFAULT;
    }
    return null;
}
总结

没错,就是在findNameForDeserialization里面找到了JsonProperty定义的value,之后会在_renameProperties里面替换掉我们的 “cc"为 ”aaBB"。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
@ApiModelProperty和@JsonProperty都是用于在接口文档中展示属性信息的注解。 @ApiModelProperty注解用于描述属性接口文档中的展示信息,包括属性的描述内容、示例值等。它可以提供给开发人员和使用者更加清晰地了解接口的属性含义和使用方式。例如,在代码中使用@ApiModelProperty(value = "描述内容")可以指定属性的描述信息为"描述内容",在接口文档中展示会显示该描述信息。 @JsonProperty注解用于在序列化和反序列化过程中指定属性称。通过@JsonProperty注解,我们可以将属性称映射为不同的值。这对于在不同的系统或者平台之间的数据传输非常有用。例如,我们可以使用@JsonProperty(value = "aaBB")将属性cc的称修改为"aaBB",在序列化和反序列化过程中使用新的称。 总结起来,@ApiModelProperty主要用于接口文档的展示,提供属性的描述信息,而@JsonProperty主要用于属性称的映射,可以改变属性在序列化和反序列化过程中的称。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [同使用@JsonProperty和@ApiModelProperty,在接口文档属性该是啥???](https://blog.csdn.net/weixin_42260270/article/details/104055274)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [记录:@JSONField和@JsonProperty和@ApiModelProperty一起使用,swagger显示不正常](https://blog.csdn.net/weixin_39309402/article/details/121694303)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值