json - 如何将相同值编组和解组为具有不同类型的结构?
问题描述
我正在调用一个外部 API,我将其解组为一个结构。
在响应中,大多数字段都是整数,但由于它是 json,因此有几种极端情况可以返回字符串但仍然是有效/有用的信息:“NaN”、“N/A”
我的结构是这样的:
type Example struct {
Field1 *int64 `json:"field_1,omitempty"`
Field2 *int64 `json:"field_2,omitempty"`
Field3 *int64 `json:"field_3,omitempty"`
}
我们有几个要求:
如果 api 返回 NaN 或 N/AI 应该在 FE 中向我的用户显示一个错误,所以我正在考虑用 null 替换这些值,同时事先“捕获”错误,这就是我选择指针值的原因。
如果没有返回值,则在重新编组时完全省略该值。
为了做到这一点,我试图用 JSON 替换“NaN”null
值
b = bytes.Replace(b, []byte("NaN"), []byte("null"), -1) `
但它不起作用,因为"null"
不等于null
,这是第一个问题。
第二个问题是 omitempty 在重新编组时也不区分 nil、0 和空值。
所以重新编组也失败了。我知道这是一个正在修复的“常见”问题,但现在有解决方法吗?
因为如果我为“ N/A ”和“NaN”传递 nil 并使用 omitempty 它将删除它们。如果我通过 0 它将没有意义(商业明智,因为 0 具有“未初始化”以外的含义)并且如果我删除 Omitempty 它将每次都编组整个结构(大量不必要的数据)并且无法区分 nil ( NA / NaN ) 和 nil ( 无值 )。
最后一个选项是像这样构建自定义类型和编组/解组器:
type JSONint64 struct {
value *int64
error string
}
但这需要我每次都检查我的 json 响应中的每个数字,而实际上 NaN 和 N/A 是非常罕见的情况,并在前端增加了“复杂性”。
我假设这是一个常见问题,因为 JSON 是无类型的,这通常是如何解决的?
解决方案
我会解组一个map[string]interface{}
值,然后使用反射或类型断言来确定值的数据类型。
Unmarshal 将其中一项存储在接口值中:
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
像这样:
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)
}
推荐阅读
- opengl - 雅可比逆运动学给出正确但尴尬的结果?
- jquery - Django AJAX 'GET' 表单 csrf_token 不适用于 'POST'
- spring - 如何将位于依赖项中的自动实现的存储库注册为 bean?
- regex - 正则表达式 - 允许字母数字、空格和符号,但不能只是数字、符号或空格。里面必须有字母
- r - R中的成对误差估计产生了错误的产品
- excel - 如何防止多个用户编辑同一个 Excel 文件?
- javascript - 如何使用 gulp.js 最小化 wordpress css 和 javascript
- angular - 如何使用 FormGroup 显示布尔值?
- javascript - 球盒碰撞检测
- javascript - 如何使用 datepicker 在 javascript 中获取 ZIG-ZAG 格式的日期