将JSON解组为最小类型

将JSON解组为最小类型,json,go,unmarshalling,Json,Go,Unmarshalling,我有一个Json字符串要解组。 这是有效的: jsonString := []byte(`{"my_int": 3, "my_string": null}`) var data map[string]interface{} err := json.Unmarshal(jsonString, &data) if err != nil { fmt.Println(err) } //avroJson := make(map[string]interface{}) for k, v :=

我有一个Json字符串要解组。 这是有效的:

jsonString := []byte(`{"my_int": 3, "my_string": null}`)
var data map[string]interface{}
err := json.Unmarshal(jsonString, &data)
if err != nil {
    fmt.Println(err)
}
//avroJson := make(map[string]interface{})
for k, v := range data {
    fmt.Printf("%v, %T\n", k, v)
}
我的问题是:
My_int
的值3返回为float64

我的问题是:如何解析具有“最小类型”的json字符串,以便
3
将返回
int32
,而不是最大类型
3
=>
float64

假设:我的Json很大,只有基本类型,我希望最小值为float64,以继续显示
float64

澄清: “最小类型”意味着如果
3
可以同时考虑
int32
float64
,“最小类型”将是
int32
,这正是运行此操作时得到的类型:
reflect.TypeOf(3).string()

由于您要解组到
接口{}
的映射中,以下部分适用于:

要将JSON解组为接口值,解组将其中一个存储在接口值中:

float64,用于JSON编号
字符串,用于JSON字符串

因此,要将示例数据解组为所需类型,应定义包含所需字段/类型映射的结构类型,例如:

type MyType struct {
    MyInt    int     `json:"my_int"`
    MyString *string `json:"my_string"`
}

foo := MyType{}
jsonstr := `{"my_int": 3, "my_string": null}`

err := json.Unmarshal([]byte(jsonstr), &foo)
if err != nil {
    panic(err)
}
// foo => main.MyType{MyInt:3, MyString:(*string)(nil)}

由于无法在结构中描述数据,因此您可以选择:

  • 在解析值时,使用将其转换为所需的类型

  • 将文档解析为通用接口并对值类型进行后期处理

  • 选项#1是最灵活的,并且可能比其他选项实现的性能更好,因为解析和转换可以在一次数据传递中执行

    选项2可能更简单,但需要对数据进行两次传递。以下是后处理步骤的示例:

    func TransformValueTypes(o map[string]interface{}) {
      for k, v := range o {
        // Convert nil values to *string type.
        if v == interface{}(nil) {
          o[k] = (*string)(nil)
        }
        // Convert numbers to int32 if possible
        if x, isnumber := v.(float64); isnumber {
          if math.Floor(x) == x {
            if x >= math.MinInt32 && x <= math.MaxInt32 {
              o[k] = int32(x)
            }
            // Possibly check for other integer sizes here?
          }
          // Possibly check if float32 is possible here?
        }
        // Check for maps and slices here...
      }
    }
    
    // my_int     -> 3     (int32)
    // my_string  -> <nil> (*string)
    // my_string2 -> "foo" (string)
    // my_float   -> 1.23  (float64)
    
    当然,转换函数也可以基于键名应用类型转换逻辑


    重要的是,请注意,如果您的文档可能有问题中未提及的其他结构(如嵌套对象或数组),则转换函数需要通过更多的值类型检查、递归调用和迭代来解释这些结构。

    定义结构。如果你解析接口{},你会直截了当地说“我不在乎类型”。你的术语“最小类型”和“最大类型”令人困惑。类型是不可比较的。。。我真的不知道这意味着什么。JSON是基于JavaScript的,在JavaScript中所有的数字都是float64,所以除非你指定一个类型,否则数字将被解码成float64。我明白你在说什么,所以让我们从更简单的开始。我想
    Json.Unmarshel()
    将每个值float64键入int,而不指定特定的键名。这可能吗。看看@maerics的答案和我对它的评论,他离我想做的事情越来越近了。显然,在
    解组后,我可以编写一个方法来完成这项工作,我正在寻找一种避免额外转换方法的方法。谢谢,但正如我在假设中提到的,我的Json文件是巨大的、动态的。我无法指定每隔几周按名称更改的100个键。我试图找出如何编写类似于您的答案的内容,而不指定特定的键,如
    my_int
    my_string
    。有什么想法吗有没有办法通过值类型而不是键名来指定Json结构转换?这是一个很好的答案,它与我自己的实现非常相似-我使用的是结构和开关案例来为我进行检查。一个很好的解决方案是演示如何使用Json解码器,只需一次,但不声明映射键,这是我没有做到的。谢谢你的努力,值得投票表决。顺便说一句,我根据你的反馈对我的问题进行了澄清。。