Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,11 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context

// hack to avoid clobbering properties with get/is names
// it's ugly but gets around https://github.com/swagger-api/swagger-core/issues/415
if (propDef.getPrimaryMember() != null) {
// Skip it when a PropertyNamingStrategy is configured: propName already reflects the
// strategy-translated name, and falling back to the raw member name (e.g. a record
// accessor such as "issuanceDate") would wrongly leave "is"-prefixed names untranslated.
if (propDef.getPrimaryMember() != null
&& _mapper.getSerializationConfig().getPropertyNamingStrategy() == null) {
final JsonProperty jsonPropertyAnn = propDef.getPrimaryMember().getAnnotation(JsonProperty.class);
if (jsonPropertyAnn == null || !jsonPropertyAnn.value().equals(propName)) {
if (member != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.swagger.v3.java17.resolving;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import io.swagger.v3.core.converter.AnnotatedType;
import io.swagger.v3.core.converter.ModelConverterContextImpl;
import io.swagger.v3.core.jackson.ModelResolver;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.java17.matchers.SerializationMatchers;
import org.testng.annotations.Test;

public class Ticket3293Test extends SwaggerTestBase {

@Test
public void testSnakeCaseNamingWithIsPrefixedRecordComponents() {
ModelResolver modelResolver = new ModelResolver(
Json.mapper().copy().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE));
ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver);
context.resolve(new AnnotatedType(PidLookupResponse.class));

// Every component must be snake_cased, including the non-boolean "is"-prefixed ones
// (issuanceDate / issuingCountry / issuingAuthority) which used to leak through as camelCase.
// A genuine boolean accessor (isActive) keeps behaving correctly.
String expectedYaml = "PidLookupResponse:\n" +
" type: object\n" +
" properties:\n" +
" family_name:\n" +
" type: string\n" +
" expiry_date:\n" +
" type: string\n" +
" issuance_date:\n" +
" type: string\n" +
" issuing_country:\n" +
" type: string\n" +
" issuing_authority:\n" +
" type: string\n" +
" is_active:\n" +
" type: boolean";

SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), expectedYaml);
}

record PidLookupResponse(
String familyName,
String expiryDate,
String issuanceDate,
String issuingCountry,
String issuingAuthority,
boolean isActive
) {
}
}