Files
prompts-core/common/util/json.go

198 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package util
import (
"encoding/json"
"fmt"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/util/gconv"
)
// ConvertToMessages 将原始数据转换为消息列表
func ConvertToMessages(raw any) []map[string]any {
if raw == nil {
return nil
}
j := gjson.New(raw)
messages := j.Get("messages")
if !messages.IsNil() {
return gconv.Maps(messages.Val())
}
return []map[string]any{j.Map()}
}
// FormToJSON 将表单数据转换为 JSON 字符串
func FormToJSON(form []map[string]any) string {
if form == nil {
return "[]"
}
b, _ := json.Marshal(form)
return string(b)
}
// UserFormToJSON 将用户表单数据转换为 JSON 字符串
func UserFormToJSON(form []map[string]any) string {
if form == nil {
return "{}"
}
b, _ := json.Marshal(form)
return string(b)
}
// MustMarshalToMap 将对象序列化为 map[string]any失败时返回空 map
func MustMarshalToMap(v any) map[string]any {
b, err := json.Marshal(v)
if err != nil {
return make(map[string]any)
}
var m map[string]any
json.Unmarshal(b, &m)
return m
}
// JSONPretty 将任意类型转为格式化的 JSON 字符串
func JSONPretty(v any) string {
if gv, ok := v.(*gvar.Var); ok {
v = gconv.Map(gv.String())
}
var tmp map[string]any
if err := gconv.Struct(v, &tmp); err != nil {
return gconv.String(v)
}
b, _ := json.Marshal(tmp)
return string(b)
}
// ParseJSONFieldFromGvar 专门处理 *gvar.Var 类型的 JSON 字段解析
func ParseJSONFieldFromGvar(source any, target any) {
if source == nil {
return
}
switch v := source.(type) {
case *gvar.Var:
if v.IsNil() {
return
}
// 尝试获取 map
if m := v.Map(); len(m) > 0 {
data, _ := json.Marshal(m)
json.Unmarshal(data, target)
return
}
// 尝试解析 JSON 字符串
str := v.String()
if str != "" && str != "<nil>" {
json.Unmarshal([]byte(str), target)
}
default:
// 其他类型走原来的逻辑
data, _ := json.Marshal(source)
json.Unmarshal(data, target)
}
}
// MergeConsult 将 consult 附件合并到模型生成的 messages 结构中
func MergeConsult(req map[string]any, messages map[string]any, extendMapping map[string]any) map[string]any {
if len(req) == 0 || len(messages) == 0 || len(extendMapping) == 0 {
return messages
}
// 1) 获取 consult 数组
consult := gconv.Interfaces(req["consult"])
if len(consult) == 0 {
return messages
}
// 2) 获取配置
targetPath := gconv.String(extendMapping["target_content_path"])
if targetPath == "" {
return messages
}
templates := gconv.Map(extendMapping["attachment_templates"])
if len(templates) == 0 {
return messages
}
// 3) 转为 gjson 操作
msgJson := gjson.New(messages)
// 固定:如果有 rounds 结构,路径替换为 rounds.0.{targetPath}
if arr := msgJson.Get("rounds.0").Array(); arr != nil {
targetPath = "rounds.0." + targetPath
}
// 4) 遍历 consult按类型生成附件并追加
for _, item := range consult {
itemJson := gjson.New(item)
itemType := itemJson.Get("type").String()
if itemType == "" {
continue
}
// 查找对应模板
tmpl := gconv.Map(templates[itemType])
if len(tmpl) == 0 {
continue
}
// 生成附件对象
attachment := buildAttachment(tmpl, itemJson.Get("url").String())
if attachment == nil {
continue
}
// 获取当前数组长度,用索引追加
arr := msgJson.Get(targetPath).Array()
idx := len(arr)
indexPath := fmt.Sprintf("%s.%d", targetPath, idx)
_ = msgJson.Set(indexPath, attachment)
}
return msgJson.Map()
}
// buildAttachment 根据模板和用户数据生成附件对象
func buildAttachment(tmpl map[string]any, url string) map[string]any {
typ := gconv.String(tmpl["type"])
if typ == "" || url == "" {
return nil
}
// 深拷贝 body 并填充 url
body := gconv.Map(tmpl["body"])
bodyJson := gjson.New(body)
bodyJson = fillEmpty(bodyJson, url)
return map[string]any{
"type": typ,
typ: bodyJson.Map(),
}
}
// fillEmpty 递归查找空字符串并替换
func fillEmpty(j *gjson.Json, value string) *gjson.Json {
m := j.Map()
for k, v := range m {
switch vv := v.(type) {
case string:
if vv == "" {
_ = j.Set(k, value)
}
case map[string]any:
_ = j.Set(k, fillEmpty(gjson.New(vv), value).Map())
}
}
return j
}