result.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package compapi
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "strings"
  8. "wechat-api/internal/types"
  9. )
  10. // 包装了原始的 API 响应,并提供了解析助手方法
  11. type ChatResult struct {
  12. *types.CompOpenApiResp
  13. err error
  14. }
  15. // NewChatResult 是 ChatResult 的构造函数
  16. func NewChatResult(resp any) *ChatResult {
  17. nresp, err := AnyToCompOpenApiResp(resp)
  18. res := ChatResult{nresp, err}
  19. if nresp == nil {
  20. res.err = errors.New("CompOpenApiRes is nil")
  21. }
  22. return &res
  23. }
  24. // 以下是ChatResul助手方法
  25. // GetContentString 返回第一个 Choice 的 Message Content (标准方式)
  26. func (r *ChatResult) GetContentString() (string, error) {
  27. var (
  28. content string = ""
  29. err error
  30. )
  31. if r.err == nil && len(r.Choices) > 0 {
  32. content = r.Choices[0].Message.Content
  33. } else if r.err == nil && len(r.Choices) == 0 {
  34. err = errors.New("choices empty")
  35. }
  36. return content, err
  37. }
  38. // ParseContentAs 解析 Message Content 中的 JSON 到指定的 Go 结构体
  39. // target 必须是一个指向目标结构体实例的指针 (e.g., &MyStruct{})
  40. func (r *ChatResult) ParseContentAs(target any) error {
  41. content, err := r.GetContentString()
  42. if err != nil {
  43. return fmt.Errorf("parseContent err: %s", err)
  44. } else if content == "" {
  45. return errors.New("parseContent err: content is empty or unavailable")
  46. }
  47. // (可选)清理可能的 Markdown ```json ``` 包装
  48. if strings.HasPrefix(content, "```json") && strings.HasSuffix(content, "```") {
  49. content = strings.TrimSuffix(strings.TrimPrefix(content, "```json"), "```")
  50. content = strings.TrimSpace(content)
  51. }
  52. err = json.Unmarshal([]byte(content), target)
  53. if err != nil {
  54. return fmt.Errorf("parseContent err: failed to unmarshal content JSON into target type '%w'", err)
  55. }
  56. return nil
  57. }
  58. func AnyToBytes(in any) ([]byte, error) {
  59. switch v := in.(type) {
  60. case string:
  61. return []byte(v), nil
  62. case []byte:
  63. return v, nil
  64. default:
  65. return json.Marshal(v)
  66. }
  67. }
  68. func AnyToCompOpenApiResp(in any) (*types.CompOpenApiResp, error) {
  69. if resp, ok := in.(*types.CompOpenApiResp); ok {
  70. return resp, nil
  71. }
  72. if resp, ok := in.(types.CompOpenApiResp); ok {
  73. return &resp, nil
  74. }
  75. bs, err := AnyToBytes(in)
  76. if err != nil {
  77. return nil, err
  78. }
  79. nresp := &types.CompOpenApiResp{}
  80. err = json.Unmarshal(bs, nresp)
  81. if err != nil {
  82. return nil, err
  83. }
  84. return nresp, nil
  85. }
  86. func AnyToCompApiReq(in any) (*types.CompApiReq, error) {
  87. if req, ok := in.(*types.CompApiReq); ok {
  88. return req, nil
  89. }
  90. if req, ok := in.(types.CompApiReq); ok {
  91. return &req, nil
  92. }
  93. bs, err := AnyToBytes(in)
  94. if err != nil {
  95. return nil, err
  96. }
  97. nreq := &types.CompApiReq{}
  98. err = json.Unmarshal(bs, nreq)
  99. if err != nil {
  100. return nil, err
  101. }
  102. return nreq, nil
  103. }
  104. func CheckJSON(input any, checkEmpty bool) (bool, error) {
  105. inputBytes, err := AnyToBytes(input)
  106. if err != nil {
  107. return false, err
  108. }
  109. var raw json.RawMessage
  110. err = json.Unmarshal(inputBytes, &raw)
  111. if err != nil {
  112. return false, fmt.Errorf("input is not valid JSON: %w", err)
  113. }
  114. if checkEmpty {
  115. trimmed := bytes.TrimSpace(inputBytes)
  116. if len(trimmed) == 0 {
  117. return false, fmt.Errorf("input is empty")
  118. }
  119. }
  120. return true, nil
  121. }
  122. func WrapJSON(input any, warpKey string, checkValid bool) ([]byte, error) {
  123. var (
  124. inputBytes []byte
  125. outputBytes []byte
  126. err error
  127. )
  128. if inputBytes, err = AnyToBytes(input); err != nil {
  129. return nil, err
  130. }
  131. if checkValid {
  132. if _, err = CheckJSON(inputBytes, true); err != nil {
  133. return nil, err
  134. }
  135. }
  136. if len(warpKey) == 0 {
  137. return inputBytes, nil
  138. }
  139. wrapper := map[string]json.RawMessage{
  140. warpKey: json.RawMessage(inputBytes),
  141. }
  142. if outputBytes, err = json.Marshal(wrapper); err != nil {
  143. return nil, fmt.Errorf("failed to marshal wrapper structure: %w", err)
  144. }
  145. return outputBytes, nil
  146. }