Skip to content

Conversation

@betterlmy
Copy link

🐛 Problem Description

When using case-insensitive field matching, copier may incorrectly match unexported fields when the target struct contains both exported (e.g., State) and unexported fields (e.g., state) with similar names, leading to copy failures or data loss.

This issue is particularly common when working with protobuf-generated structs, as the protobuf compiler generates structs containing both public and private fields.

Reproduction Scenario

type ProtoStruct struct {
    state      uint32  // internal protobuf field
    State      int32   `json:"state"` // public field
}

type SourceStruct struct {
    State int32 `json:"state"`
}

In case-insensitive mode, copier might match the private state field instead of the public State field, causing copy operations to fail.

✅ Solution

Reimplemented the case-insensitive matching logic in the fieldByName function:

  1. Exact Match First: Attempt exact field name matching initially
  2. Collect Candidates: If exact matching fails, collect all case-insensitive matching fields
  3. Prioritize Exported Fields: Among multiple candidates, prioritize exported fields (starting with uppercase letter)
  4. Backward Compatibility: If no exported field is found, return the first match (preserving original behavior)

Key Improvements

  • 🔍 Smart field priority: Exported fields > Unexported fields
  • 🚀 Better protobuf support
  • 📦 Maintains backward compatibility
  • ✨ Aligns with Go's field access conventions

🧪 Test Coverage

Added comprehensive test cases:

  • ✅ Test exported/unexported field priority selection
  • ✅ Test exact matching still works correctly
  • ✅ Test field copying in protobuf scenarios
  • ✅ Verify backward compatibility

📋 Changes

  • Fixed fieldByName function in copier.go
  • Added copier_case_insensitive_test.go test file
  • Maintained API compatibility
  • All existing tests pass

🔄 Impact

This fix:

  • ✅ Resolves protobuf-generated struct copying issues
  • ✅ Improves field matching accuracy
  • ✅ Won't break existing code
  • ✅ Follows Go's exported field priority principle

📚 Background

This fix addresses field matching ambiguity encountered in real-world projects using copier, particularly in microservice architectures using protobuf. The solution ensures that when multiple fields match case-insensitively, the library intelligently selects the most appropriate field according to Go's visibility conventions.

🧪 Testing

go test -v ./... -run TestCaseInsensitiveFieldMatching
go test -v ./...

All tests pass, confirming the fix works correctly while maintaining backward compatibility.

@betterlmy
Copy link
Author

@jinzhu copier is very important in our company's development but this bug has troubled us for a long time... Please help me review this PR.
Code is generated by claude-4-sonnet.

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