refactor(*): 稳定期治理 - 收敛核心架构、错误语义并修复跨项目数据竞态
This commit is contained in:
59
backend/internal/service/json_fields.go
Normal file
59
backend/internal/service/json_fields.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// optionalJSONString reads an optional untyped JSON string.
|
||||
// Missing or null yields "". A present non-string is a protocol error and is not coerced.
|
||||
func optionalJSONString(payload map[string]any, key string) (string, error) {
|
||||
if payload == nil {
|
||||
return "", nil
|
||||
}
|
||||
value, ok := payload[key]
|
||||
if !ok || value == nil {
|
||||
return "", nil
|
||||
}
|
||||
text, ok := value.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("field %s: expected string, got %T", key, value)
|
||||
}
|
||||
return text, nil
|
||||
}
|
||||
|
||||
// requireJSONString reads a required non-empty JSON string.
|
||||
func requireJSONString(payload map[string]any, key string) (string, error) {
|
||||
text, err := optionalJSONString(payload, key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
text = strings.TrimSpace(text)
|
||||
if text == "" {
|
||||
return "", fmt.Errorf("missing field: %s", key)
|
||||
}
|
||||
return text, nil
|
||||
}
|
||||
|
||||
// firstJSONString returns the first present non-empty string among keys.
|
||||
// Missing keys are skipped. A present non-string is a protocol error unless a later key supplies a valid string.
|
||||
func firstJSONString(payload map[string]any, keys ...string) (string, error) {
|
||||
var typeErr error
|
||||
for _, key := range keys {
|
||||
text, err := optionalJSONString(payload, key)
|
||||
if err != nil {
|
||||
if typeErr == nil {
|
||||
typeErr = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
text = strings.TrimSpace(text)
|
||||
if text != "" {
|
||||
return text, nil
|
||||
}
|
||||
}
|
||||
if typeErr != nil {
|
||||
return "", typeErr
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
Reference in New Issue
Block a user