thread-master/internal/library/viral/flexible_json.go

142 lines
3.7 KiB
Go
Raw Permalink Normal View History

2026-06-26 08:37:04 +00:00
package viral
import (
"encoding/json"
"strings"
)
func firstJSONString(obj map[string]json.RawMessage, keys ...string) string {
for _, key := range keys {
raw, ok := obj[key]
if !ok {
continue
}
var value string
if err := json.Unmarshal(raw, &value); err == nil {
if trimmed := strings.TrimSpace(value); trimmed != "" {
return trimmed
}
}
}
return ""
}
func flexibleStringFromItem(raw json.RawMessage) string {
if len(raw) == 0 {
return ""
}
var value string
if err := json.Unmarshal(raw, &value); err == nil {
return strings.TrimSpace(value)
}
var obj map[string]json.RawMessage
if err := json.Unmarshal(raw, &obj); err != nil {
return ""
}
if line := firstJSONString(obj, "title", "name", "label", "pillar", "tag", "text", "summary", "description", "value", "content"); line != "" {
return line
}
parts := []string{}
for _, key := range []string{"title", "name", "label"} {
if part := firstJSONString(obj, key); part != "" {
parts = append(parts, part)
break
}
}
if detail := firstJSONString(obj, "description", "summary", "detail", "reason"); detail != "" {
parts = append(parts, detail)
}
return strings.TrimSpace(strings.Join(parts, ""))
}
func parseFlexibleStringList(raw json.RawMessage) []string {
if len(raw) == 0 || string(raw) == "null" {
return nil
}
var items []string
if err := json.Unmarshal(raw, &items); err == nil {
return cleanLines(items)
}
var single string
if err := json.Unmarshal(raw, &single); err == nil && strings.TrimSpace(single) != "" {
return cleanLines([]string{single})
}
var arr []json.RawMessage
if err := json.Unmarshal(raw, &arr); err != nil {
return nil
}
out := make([]string, 0, len(arr))
for _, item := range arr {
if line := flexibleStringFromItem(item); line != "" {
out = append(out, line)
}
}
return cleanLines(out)
}
func parseFlexibleSuggestedTags(raw json.RawMessage) []SuggestedTag {
if len(raw) == 0 || string(raw) == "null" {
return nil
}
var tags []SuggestedTag
if err := json.Unmarshal(raw, &tags); err == nil && len(tags) > 0 {
return cleanSuggestedTags(tags)
}
var strs []string
if err := json.Unmarshal(raw, &strs); err == nil {
out := make([]SuggestedTag, 0, len(strs))
for _, item := range strs {
item = strings.TrimSpace(item)
if item != "" {
out = append(out, SuggestedTag{Tag: item})
}
}
return cleanSuggestedTags(out)
}
var arr []json.RawMessage
if err := json.Unmarshal(raw, &arr); err != nil {
return nil
}
out := make([]SuggestedTag, 0, len(arr))
for _, item := range arr {
if tag := decodeSuggestedTagItem(item); tag.Tag != "" {
out = append(out, tag)
}
}
return cleanSuggestedTags(out)
}
func decodeSuggestedTagItem(raw json.RawMessage) SuggestedTag {
var tag SuggestedTag
if err := json.Unmarshal(raw, &tag); err == nil && strings.TrimSpace(tag.Tag) != "" {
return tag
}
var snake struct {
Tag string `json:"tag"`
Reason string `json:"reason"`
SearchIntent string `json:"search_intent"`
SearchType string `json:"search_type"`
}
if err := json.Unmarshal(raw, &snake); err == nil && strings.TrimSpace(snake.Tag) != "" {
return SuggestedTag{
Tag: strings.TrimSpace(snake.Tag),
Reason: strings.TrimSpace(snake.Reason),
SearchIntent: strings.TrimSpace(snake.SearchIntent),
SearchType: strings.TrimSpace(snake.SearchType),
}
}
if line := flexibleStringFromItem(raw); line != "" {
return SuggestedTag{Tag: line}
}
return SuggestedTag{}
}
func pickRawMessage(root map[string]json.RawMessage, keys ...string) json.RawMessage {
for _, key := range keys {
if raw, ok := root[key]; ok && len(raw) > 0 && string(raw) != "null" {
return raw
}
}
return nil
}