Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix handling of empty prop name in json tag #123

Merged
merged 1 commit into from
Jan 20, 2025
Merged

Conversation

vearutop
Copy link
Member

Copy link

Lines Of Code

Language Files Lines Code Comments Blanks Complexity Bytes
Go 7 2395 1633 275 487 632 57.8K (+5B)
Go (test) 13 4191 (+105) 3114 (+83) 311 766 (+22) 51 106.1K (+2.3K)

Copy link

Go API Changes

# summary
Inferred base version: v0.3.72
Suggested version: v0.3.73

Copy link

Unit Test Coverage

total: (statements) 80.2%
changed lines: (statements) 100.0%

Coverage of changed lines
File Function Coverage
Total 100.0%
reflect.go 100.0%
reflect.go:1023 walkProperties 100.0%
Coverage diff with base branch

No changes in coverage.

Copy link

Benchmark Result

Benchmark diff with base branch
name                        old time/op    new time/op    delta
Schema_UnmarshalJSON_raw-4    60.7µs ± 1%    60.6µs ± 1%   ~     (p=0.310 n=5+5)
Schema_UnmarshalJSON-4         479µs ± 4%     478µs ± 2%   ~     (p=0.421 n=5+5)
Schema_MarshalJSON_raw-4      43.7µs ± 1%    43.9µs ± 1%   ~     (p=0.151 n=5+5)
Schema_MarshalJSON-4           186µs ± 1%     187µs ± 1%   ~     (p=0.310 n=5+5)

name                        old alloc/op   new alloc/op   delta
Schema_UnmarshalJSON_raw-4    31.7kB ± 0%    31.7kB ± 0%   ~     (p=0.937 n=5+5)
Schema_UnmarshalJSON-4         180kB ± 0%     180kB ± 0%   ~     (p=0.444 n=5+5)
Schema_MarshalJSON_raw-4      14.6kB ± 0%    14.6kB ± 0%   ~     (all equal)
Schema_MarshalJSON-4          53.9kB ± 0%    53.9kB ± 0%   ~     (p=0.825 n=5+5)

name                        old allocs/op  new allocs/op  delta
Schema_UnmarshalJSON_raw-4       457 ± 0%       457 ± 0%   ~     (all equal)
Schema_UnmarshalJSON-4         1.85k ± 0%     1.85k ± 0%   ~     (all equal)
Schema_MarshalJSON_raw-4         370 ± 0%       370 ± 0%   ~     (all equal)
Schema_MarshalJSON-4             468 ± 0%       468 ± 0%   ~     (all equal)
Benchmark result
name                        time/op
Schema_UnmarshalJSON_raw-4  60.6µs ± 1%
Schema_UnmarshalJSON-4       478µs ± 2%
Schema_MarshalJSON_raw-4    43.9µs ± 1%
Schema_MarshalJSON-4         187µs ± 1%

name                        alloc/op
Schema_UnmarshalJSON_raw-4  31.7kB ± 0%
Schema_UnmarshalJSON-4       180kB ± 0%
Schema_MarshalJSON_raw-4    14.6kB ± 0%
Schema_MarshalJSON-4        53.9kB ± 0%

name                        allocs/op
Schema_UnmarshalJSON_raw-4     457 ± 0%
Schema_UnmarshalJSON-4       1.85k ± 0%
Schema_MarshalJSON_raw-4       370 ± 0%
Schema_MarshalJSON-4           468 ± 0%

Copy link

@llamapreview llamapreview bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto Pull Request Review from LlamaPReview

1. Overview

1.1 PR Summary

  • Business value and requirements alignment: The PR fixes an issue where empty property names in JSON tags were not handled correctly, which could lead to incorrect JSON schema generation and potential data loss. This change aligns with the library's goal of providing accurate and reliable JSON schema mapping for Go.
  • Key components modified: The PR modifies the reflect.go file, which contains the core reflection functionality of the library. It also adds new test cases in the reflect_test.go file to validate the changes.
  • Impact assessment: The changes might have implications for how the library interacts with other libraries or frameworks that use JSON tags for struct field mapping. It's essential to validate that the new behavior does not break existing functionality in dependent systems.
  • System dependencies and integration impacts: The changes might affect the library's integration with other libraries or frameworks that rely on JSON tags for struct field mapping. It's crucial to ensure that the new behavior does not introduce compatibility issues.

1.2 Architecture Changes

  • System design modifications: The PR introduces a new behavior for handling empty property names in JSON tags. This change might have implications for how the library generates JSON schemas and maps struct fields to JSON.
  • Component interactions: The changes in reflect.go might affect how the library interacts with other components that use JSON tags for struct field mapping. It's essential to validate that the new behavior does not break existing functionality in dependent components.
  • Integration points: The PR modifies the library's reflection functionality, which is a critical integration point for other libraries or frameworks that use JSON tags for struct field mapping. It's crucial to ensure that the new behavior does not introduce compatibility issues at these integration points.

2. Detailed Technical Analysis

2.1 Code Logic Deep-Dive

Core Logic Changes

  • reflect.go - walkProperties function
    • Submitted PR Code:
    for i, field := range fields {
      tag, tagFound := r.propertyTag(rc, field)

      // Skip explicitly discarded field.
      if tag == "-" {
        continue
      }

      // ... (other unchanged code)

      propName := strings.Split(tag, ",")[0]

      if propName == "" && field.Anonymous &&
        (field.Type.Kind() == reflect.Struct || deepIndirect.Kind() == reflect.Struct) {
        forceReference := (field.Type.Implements(typeOfEmbedReferencer) && field.Tag.Get("refer") == "") ||
          field.Tag.Get("refer") == "true"

        if forceReference {
          rc.Path = append(rc.Path, "")
          // ... (other unchanged code)
        }
      }

      // ... (other unchanged code)
    }
  • Analysis:
    • The PR introduces a new condition to handle empty property names in JSON tags. If the property name is empty and the field is anonymous, the code now attempts to force a reference by appending an empty string to the path. This change might have unintended consequences, as empty property names are typically not valid in JSON.
    • Edge cases and error handling: The new logic does not account for potential errors when attempting to reflect the value. It's crucial to handle any errors that might occur during this process.
    • Cross-component impact: This change might affect how the library interacts with other libraries or frameworks that use JSON tags for struct field mapping. It's essential to validate that the new behavior does not break existing functionality in dependent systems.
  • LlamaPReview Suggested Improvements:
    if propName == "" && field.Anonymous &&
      (field.Type.Kind() == reflect.Struct || deepIndirect.Kind() == reflect.Struct) {
      forceReference := (field.Type.Implements(typeOfEmbedReferencer) && field.Tag.Get("refer") == "") ||
        field.Tag.Get("refer") == "true"

      if forceReference {
        rc.Path = append(rc.Path, "")
        s, err := r.reflect(values[i].Interface(), rc, false, parent)
        if err != nil {
          // Handle the error appropriately, e.g., log it or return it to the caller.
          log.Printf("Error reflecting value: %v", err)
          continue
        }
      }
    }
  • Improvement rationale:

    • Adding error handling ensures that the function can gracefully handle any issues that arise during reflection, preventing potential panics or unexpected behavior.
    • Technical benefits: Improved robustness and stability of the library.
    • Business value: Ensures that the library behaves predictably and does not fail unexpectedly, maintaining user trust.
    • Risk assessment: Without proper error handling, the library could fail unexpectedly, leading to user frustration and potential data loss.
  • reflect_test.go - New test cases

    • Submitted PR Code:
    func TestReflector_Reflect_deeplyEmbedded_emptyJSONTags(t *testing.T) {
      // ... (other unchanged code)

      s, err := r.Reflect(val)
      require.NoError(t, err)

      // ... (other unchanged code)
    }

    func TestReflector_Reflect_deeplyEmbedded_validJSONTags(t *testing.T) {
      // ... (other unchanged code)

      s, err := r.Reflect(val)
      require.NoError(t, err)

      // ... (other unchanged code)
    }
  • Analysis:
    • The PR introduces two new test cases that cover the new behavior for empty and valid JSON tags. However, these tests do not cover the edge case where the JSON tag is empty, but the field is not anonymous.
    • Edge cases and error handling: The new test cases do not account for potential errors that might occur during reflection. It's crucial to validate that the library can handle these errors gracefully.
    • Business logic considerations: The new test cases focus on validating the JSON schema generation, but they do not cover the actual reflection and mapping of struct fields to JSON. It's essential to ensure that the library can correctly map struct fields to JSON, regardless of the JSON tag's content.
  • LlamaPReview Suggested Improvements:
    • Add a new test case to cover the edge case where the JSON tag is empty, but the field is not anonymous.
    • Modify the existing test cases to include error handling and validation of the reflection process.
  • Improvement rationale:
    • Expanding test coverage to include edge cases and error handling ensures that the library behaves predictably under various conditions.
    • Technical benefits: Improved test coverage and reduced likelihood of undetected bugs.
    • Business value: Enhanced user trust through thorough testing and validation of the library's functionality.
    • Risk assessment: Inadequate test coverage could lead to undetected bugs, user frustration, and potential data loss.

2.2 Implementation Quality

  • Code organization and structure: The PR maintains a clear and organized structure, with changes focused on the relevant files (reflect.go and reflect_test.go). The changes are well-documented with comments and follow the existing coding style.
  • Design patterns usage: The PR does not introduce any new design patterns. It builds upon the existing reflection functionality and extends it to handle empty property names in JSON tags.
  • Error handling approach: The PR introduces error handling in the walkProperties function to ensure that the library can gracefully handle any issues that arise during reflection. However, the new test cases do not include error handling, which should be addressed.
  • Resource management: The PR does not introduce any new resources that need to be managed. It focuses on modifying the existing reflection functionality and adding new test cases.

3. Critical Findings

3.1 Potential Issues

  • 🔴 Critical Issues
    • Impact: The new behavior for handling empty property names in JSON tags might break existing functionality, leading to unexpected behavior or failures in dependent systems.
    • Recommendation: Thoroughly test the new behavior with various edge cases, including empty JSON tags, non-empty tags, and different data types. Validate that existing functionality is not broken by the change.
  • 🟡 Warnings
    • Warning: The new test cases do not cover the edge case where the JSON tag is empty, but the field is not anonymous.
    • Potential risks: Inadequate test coverage could lead to undetected bugs, user frustration, and potential data loss.
    • Suggested improvements: Add a new test case to cover the edge case where the JSON tag is empty, but the field is not anonymous. Modify the existing test cases to include error handling and validation of the reflection process.

3.2 Code Quality Concerns

  • Maintainability aspects: The PR maintains good maintainability, with clear and concise changes focused on the relevant files. However, the new test cases could be improved to include error handling and validation of the reflection process.
  • Readability issues: The PR maintains good readability, with clear comments and a well-organized structure. However, some code comments could be improved to better explain the purpose and functionality of the changes.
  • Performance bottlenecks: The PR does not introduce any new performance bottlenecks. The changes focus on modifying the existing reflection functionality and adding new test cases.

4. Security Assessment

  • Authentication/Authorization impacts: The PR does not introduce any new authentication or authorization impacts. It focuses on modifying the existing reflection functionality and adding new test cases.
  • Data handling concerns: The PR does not introduce any new data handling concerns. It maintains the existing data handling functionality and ensures that the library can correctly map struct fields to JSON, regardless of the JSON tag's content.
  • Input validation: The PR does not introduce any new input validation concerns. It maintains the existing input validation functionality and ensures that the library can handle various edge cases, including empty JSON tags.
  • Security best practices: The PR follows security best practices, such as using error handling to prevent unexpected behavior and panics. However, the new test cases could be improved to include validation of the reflection process and error handling.
  • Potential security risks: Without proper error handling and validation of the reflection process, the library could fail unexpectedly, leading to user frustration and potential data loss.
  • Mitigation strategies: Thoroughly test the new behavior with various edge cases, including empty JSON tags, non-empty tags, and different data types. Validate that existing functionality is not broken by the change. Add a new test case to cover the edge case where the JSON tag is empty, but the field is not anonymous. Modify the existing test cases to include error handling and validation of the reflection process.
  • Security testing requirements: The PR introduces new test cases that cover the new behavior for empty and valid JSON tags. However, these tests do not cover the edge case where the JSON tag is empty, but the field is not anonymous. It's essential to ensure that the library can handle these edge cases gracefully and validate the reflection process.

5. Testing Strategy

5.1 Test Coverage

  • Unit test analysis: The PR introduces new test cases that cover the new behavior for empty and valid JSON tags. However, these tests do not cover the edge case where the JSON tag is empty, but the field is not anonymous.
  • Integration test requirements: The PR does not introduce any new integration test requirements. It maintains the existing integration test functionality and ensures that the library can correctly map struct fields to JSON, regardless of the JSON tag's content.
  • Edge cases coverage: The PR introduces new test cases that cover the new behavior for empty and valid JSON tags. However, these tests do not cover the edge case where the JSON tag is empty, but the field is not anonymous. It's essential to ensure that the library can handle these edge cases gracefully and validate the reflection process.

5.2 Test Recommendations

Suggested Test Cases

  func TestReflector_Reflect_edgeCaseEmptyTagNonAnonymousField(t *testing.T) {
    r := jsonschema.Reflector{}

    type My struct {
      Foo string `json:",omitempty"`
    }

    val := My{}
    val.Foo = "abcde"

    s, err := r.Reflect(val)
    require.NoError(t, err)

    // Validate the reflection process and error handling.
  }
  • Coverage improvements: Add a new test case to cover the edge case where the JSON tag is empty, but the field is not anonymous. Modify the existing test cases to include error handling and validation of the reflection process.
  • Performance testing needs: The PR does not introduce any new performance testing needs. It maintains the existing performance testing functionality and ensures that the library can handle various edge cases, including empty JSON tags, gracefully.

6. Documentation & Maintenance

  • Documentation updates needed: The PR introduces new test cases that cover the new behavior for empty and valid JSON tags. However, these tests do not cover the edge case where the JSON tag is empty, but the field is not anonymous. It's essential to update the documentation to reflect these changes and ensure that users are aware of the new behavior and edge cases.
  • Long-term maintenance considerations: The PR maintains good long-term maintenance considerations, with clear and concise changes focused on the relevant files. However, the new test cases could be improved to include error handling and validation of the reflection process, which would enhance the library's stability and reliability over time.
  • Technical debt and monitoring requirements: The PR does not introduce any new technical debt or monitoring requirements. It maintains the existing technical debt and monitoring requirements and ensures that the library can handle various edge cases, including empty JSON tags, gracefully.

7. Deployment & Operations

  • Deployment impact and strategy: The PR does not introduce any new deployment impacts or strategies. It maintains the existing deployment functionality and ensures that the library can be deployed seamlessly, regardless of the JSON tag's content.
  • Key operational considerations: The PR maintains good operational considerations, with clear and concise changes focused on the relevant files. However, the new test cases could be improved to include error handling and validation of the reflection process, which would enhance the library's stability and reliability in production environments.

8. Summary & Recommendations

8.1 Key Action Items

  1. Thoroughly test the new behavior for handling empty property names in JSON tags with various edge cases, including empty JSON tags, non-empty tags, and different data types. Validate that existing functionality is not broken by the change.
  2. Add a new test case to cover the edge case where the JSON tag is empty, but the field is not anonymous. Modify the existing test cases to include error handling and validation of the reflection process.
  3. Update the documentation to reflect the changes and ensure that users are aware of the new behavior and edge cases.

8.2 Future Considerations

  • Technical evolution path: As the library evolves, it's essential to ensure that the new behavior for handling empty property names in JSON tags remains compatible with existing functionality and does not introduce new issues or break existing functionality in dependent systems.
  • Business capability evolution: As the library's capabilities evolve, it's crucial to ensure that the new behavior for handling empty property names in JSON tags aligns with the library's goals and maintains user trust.
  • System integration impacts: As the library integrates with other libraries or frameworks, it's essential to validate that the new behavior for handling empty property names in JSON tags does not introduce compatibility issues or break existing functionality in dependent systems.

💡 Help Shape LlamaPReview
How's this review format working for you? Vote in our Github Discussion Polls to help us improve your review experience!

@vearutop vearutop merged commit 8a67fbf into master Jan 20, 2025
7 checks passed
@vearutop vearutop deleted the embed-empty-tag branch January 20, 2025 20:59
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.

JSON inline parsing is incorrect for OpenAPI spec generation
1 participant