首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何以相同的价值将不同类型的结构分解成不同类型的结构?

如何以相同的价值将不同类型的结构分解成不同类型的结构?
EN

Stack Overflow用户
提问于 2020-09-04 11:00:28
回答 1查看 685关注 0票数 0

我正在调用一个外部API,我正在将其分解为一个结构。

在响应中,大多数字段是整数,但由于它是json,有几种边缘情况下,它可以返回字符串,但仍然是一个有效/有用的信息:"NaN“、"N/A”

我的结构是这样的:

代码语言:javascript
运行
复制
type Example struct {
  Field1 *int64 `json:"field_1,omitempty"`
  Field2 *int64 `json:"field_2,omitempty"`
  Field3 *int64 `json:"field_3,omitempty"`
}

我们有几项要求:

  • 如果api返回NaN或N/A,我应该在FE中向我的用户显示一个错误,所以我考虑在“捕获”错误之前用null替换值,这就是我选择指针值的原因。
  • 如果没有返回值,则在重新编组时完全省略该值。

为此,我尝试将"NaN“值替换为JSON null do

代码语言:javascript
运行
复制
 b = bytes.Replace(b, []byte("NaN"), []byte("null"), -1) ` 

但是它不能工作,因为"null"不等于null,这是第一个问题。

第二个问题是,在再婚时,省略也没有区分0、0和空值。

所以再婚也失败了。我知道在go 正在修理中中这是一个“常见”的问题,但是现在有工作要做吗?

因为如果我将“N/A”和"NaN“的零传递给空,它就会删除它们。如果我传递0,它就没有意义(从业务上讲,0除了“未初始化”之外还有其他含义),如果我删除Omitempty,它将在每次(大量不必要的数据)中对整个结构进行整理,并且无法区分nil ( NA / NaN )和nil (无值)。

最后一个选项是构建一个自定义类型和马歇尔/解封组器,如下所示:

代码语言:javascript
运行
复制
type JSONint64 struct {
  value *int64
  error string
}

但这将要求我检查json响应中的每个数字,每次,实际上,NaN和N/A是非常罕见的,并且在前端增加了“复杂性”。

我假设这是一个常见的问题,因为JSON是非类型化的,这通常是如何解决的?

EN

回答 1

Stack Overflow用户

发布于 2020-09-04 11:59:10

我会将法警转换为map[string]interface{}值,然后使用反射或类型断言来计算值的数据类型。

解组将其中一个存储在接口值中:

代码语言:javascript
运行
复制
bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null

就像这样:

代码语言:javascript
运行
复制
package main

import (
    "encoding/json"
    "fmt"
)

type Example struct {
    Field1 *int64 `json:"field_1,omitempty"`
    Field2 *int64 `json:"field_2,omitempty"`
    Field3 *int64 `json:"field_3,omitempty"`
}

func typeof(v interface{}) string {
    switch v.(type) {
    case float64:
        return "float64"
    case string:
        return "string"
    default:
        return "unknown"
    }
}

func main() {
    d := []byte(`{"field_1": "n/a", "field_2": 2 }"`)
    e := make(map[string]interface{})
    err := json.Unmarshal(d, &e)
    if err != nil {
        fmt.Printf("%v\n", err)
    }
    fmt.Printf("%+v\n", e)
    example := Example{}
    for k, v := range e {
        switch typeof(v) {
        case "float64":
            val := int64(v.(float64))
            switch k {
            case "field_1":
                example.Field1 = &val
            case "field_2":
                example.Field2 = &val
            case "field_3":
                example.Field3 = &val
            default:
                fmt.Printf("Unexpected field: %v\n", k)
            }

        default:
            // display error
        }
    }
    fmt.Printf("Example field_2: %d\n", *example.Field2)

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63739872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档