Skip to content

Conversation

@KushagraSingh001-crypto
Copy link

Bug Fix Analysis: Issue #10610 - String Default "1.0" Converted to "1"

Bug Description

When using Swagger-UI with application/x-www-form-urlencoded request bodies, string properties with default values like "1.0" were being incorrectly converted to "1" (losing the decimal point) when:

  1. The default value is displayed in the form
  2. The request is executed
  3. The curl command is generated

This is problematic because values like version tags (e.g., "1.0") should remain as strings and not be converted to numbers.

Root Cause

The bug occurred at multiple points in the codebase:

  1. getDefaultRequestBodyValue function: When generating default values from schema, getSampleSchema might return numeric values for string-typed properties if the default looked like a number.

  2. Initial value setting in RequestBody component: When setting initial values for form fields, the code wasn't preserving string defaults verbatim.

  3. Request execution in actions.js: When processing the request body before execution, values weren't being properly coerced to strings for string-typed properties.

  4. Reset functionality: When resetting form values, JSON parsing might lose string precision.

Fixes Applied

1. Fix in getDefaultRequestBodyValue (request-body.jsx:31-39)

const isFormLike = mediaType === "application/x-www-form-urlencoded" || mediaType.indexOf("multipart/") === 0
if (isFormLike && schema && schema.type === "object" && schema.properties && exampleValue && typeof exampleValue === "object") {
  Object.entries(schema.properties).forEach(([prop, propSchema]) => {
    const propType = Array.isArray(propSchema?.type) ? propSchema.type[0] : propSchema?.type
    if (propType === "string" && propSchema && Object.prototype.hasOwnProperty.call(propSchema, "default")) {
      exampleValue[prop] = String(propSchema.default)
    }
  })
}

What it does: After getting sample schema values, it explicitly converts string-typed properties with defaults back to strings using String(propSchema.default), preserving values like "1.0".

2. Fix in RequestBody Component (request-body.jsx:192-202)

// If schema defines a default and the property is string-typed, prefer it verbatim.
// This preserves values like "1.0" exactly as specified by the spec.
if (objectType === "string") {
  const schemaDefault = schema.get("default")
  if (schemaDefault !== undefined) {
    initialValue = String(schemaDefault)
  } else if (typeof initialValue !== "string") {
    // Otherwise ensure the sampled value is coerced to string.
    initialValue = String(initialValue)
  }
}

What it does: When setting initial values for form fields, if the schema has a default value and the property type is string, it uses String(schemaDefault) to preserve the exact string value.

3. Fix in Request Execution (actions.js:442-453)

req.requestBody = requestBody
  .map(
    (val, key) => {
      const propSchema = properties.get(key) || ImmutableMap()
      const schemaType = propSchema.get("type")
      let outVal = ImmutableMap.isMap(val) ? val.get("value") : val
      // If schema says string but value is not string, coerce
      if (schemaType === "string" && typeof outVal !== "string" && outVal !== undefined && outVal !== null) {
        outVal = String(outVal)
      }
      return outVal
    }
  )

What it does: Before executing the request, it ensures that all string-typed properties are converted to strings. This prevents numeric coercion that could turn "1.0" into 1.

4. Fix in Reset Functionality (OperationContainer.jsx:145-148)

if (schemaType === "string" && key in jsonRequestBodyValue && typeof jsonRequestBodyValue[key] !== "string") {
  jsonRequestBodyValue[key] = String(jsonRequestBodyValue[key])
}

What it does: When resetting form values, it ensures string-typed properties remain as strings after JSON parsing.

How to Test the Fix

Manual Testing Steps

  1. Create a test OpenAPI spec with the following content:
openapi: 3.0.1
info:
  title: Reproducer
  version: "1.0"
paths:
  /test:
    post:
      operationId: testOp
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Example'
      responses:
        200:
          description: "Success"
          
components:
  schemas:
    Example:
      type: object
      properties:
        versionTag:
          type: string
          default: "1.0"
  1. Load the spec in Swagger-UI:

  2. Test the default value display:

    • Click on the /test POST operation
    • Click "Try it out"
    • Verify that the versionTag input field shows "1.0" (with quotes if displayed as JSON, or just 1.0 in the input field)
    • The value should NOT be 1 or "1"
  3. Test the curl command:

    • Click "Execute" or check the generated curl command
    • The curl command should show: -d 'versionTag=1.0'
    • It should NOT show: -d 'versionTag=1'
  4. Test with user input:

    • Change the value to something else (e.g., "2.0")
    • Execute the request
    • Verify the curl command shows: -d 'versionTag=2.0'
    • Reset the form
    • Verify the value returns to "1.0" (not "1")

Automated Test (Cypress)

Create a test file: test/e2e-cypress/e2e/bugs/10047.cy.js

describe("#10047: String default '1.0' preserved for form-urlencoded", () => {
  it("should preserve string default value '1.0' exactly as specified", () => {
    cy
      .visit("?url=/documents/bugs/10047.yaml")
      .get("#operations-default-testOp")
      .click()
      // Expand Try It Out
      .get(".try-out__btn")
      .click()
      // Check that the default value is "1.0" (not "1")
      .get(`.parameters[data-property-name="versionTag"] input`)
      .should("have.value", "1.0")
      // Execute the request and check the curl command
      .get(".btn.execute")
      .click()
      // Check that the curl command contains versionTag=1.0
      .get(".curl")
      .should("contain", "versionTag=1.0")
      .should("not.contain", "versionTag=1")
  })
})

Create the test spec: test/e2e-cypress/static/documents/bugs/10047.yaml

openapi: 3.0.1
info:
  title: Reproducer
  version: "1.0"
paths:
  /test:
    post:
      operationId: testOp
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Example'
      responses:
        200:
          description: "Success"
          
components:
  schemas:
    Example:
      type: object
      properties:
        versionTag:
          type: string
          default: "1.0"

Expected Behavior After Fix

✅ Default value "1.0" is displayed correctly in the form
✅ The value "1.0" is preserved when executing the request
✅ The curl command shows versionTag=1.0 (not versionTag=1)
✅ Resetting the form restores the value to "1.0"
✅ User can change the value and it's preserved correctly

Files Modified

  1. src/core/plugins/oas3/components/request-body.jsx - Fixed default value generation and initial value setting
  2. src/core/plugins/spec/actions.js - Fixed request body processing before execution
  3. src/core/containers/OperationContainer.jsx - Fixed reset functionality

The fix(Screenshot)-

Screenshot 2025-11-02 at 12 51 35 AM Screenshot 2025-11-02 at 12 52 34 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant