我有一些JSON的形式:
[{
"type": "car",
"color": "red",
"hp": 85,
"doors": 4
}, {
"type": "plane",
"color": "blue",
"engines": 3
}]
我有满足车辆接口的car
和飞机
类型;我希望能够写:
var v []vehicle
e := json.Unmarshal(myJSON, &v)
…并让JSON用汽车和飞机填充我的车辆切片;相反(不出所料),我只是得到“无法将对象散集到main.vehicle类型的Go值中”。
作为参考,以下是相关类型的合适定义:
type vehicle interface {
vehicle()
}
type car struct {
Type string
Color string
HP int
Doors int
}
func (car) vehicle() { return }
type plane struct {
Type string
Color string
Engines int
}
func (plane) vehicle() { return }
var _ vehicle = (*car)(nil)
var _ vehicle = (*plane)(nil)
(请注意,我实际上对< code>car和< code>plane上的< code>t字段完全不感兴趣——它可以省略,因为如果有人成功回答了这个问题,此信息将隐含在< code>v中对象的动态类型中。)
有没有办法让JSON umarhsaller根据正在解码的数据的某些内容(在本例中为类型字段)选择要使用的类型?
(请注意,这不是具有未知字段的Unmarshal JSON的副本,因为我希望切片中的每个项目都具有不同的动态类型,并且从“type”属性的值中,我确切地知道需要哪些字段 - 我只是不知道如何告诉json。取消封送如何将“类型”属性值映射到 Go 类型。
Go中的JSON解码和编码实际上在识别嵌入结构中的字段方面出人意料地出色。E、 g.当A
类型和B
type T struct{
Type string `json:"type"`
*A
*B
}
type A struct{
Baz int `json:"baz"`
}
type B struct{
Bar int `json:"bar"`
}
请注意,如果在上面示例的JSON中同时设置了“baz”和“bar”,则将设置
T. A
和T. B
属性。
如果
A
和 B
之间存在重叠字段,或者只是为了能够更好地丢弃无效的字段和类型组合,则需要实现 json。解编拆解器
接口。要不必先将字段解码为映射,可以扩展使用嵌入式结构的技巧。
type TypeSwitch struct {
Type string `json:"type"`
}
type T struct {
TypeSwitch
*A
*B
}
func (t *T) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &t.TypeSwitch); err != nil {
return err
}
switch t.Type {
case "a":
t.A = &A{}
return json.Unmarshal(data, t.A)
case "b":
t.B = &B{}
return json.Unmarshal(data, t.B)
default:
return fmt.Errorf("unrecognized type value %q", t.Type)
}
}
type A struct {
Foo string `json:"bar"`
Baz int `json:"baz"`
}
type B struct {
Foo string `json:"foo"`
Bar int `json:"bar"`
}
对于封送返回,< code>json。如果有重叠字段,还必须实现Marshaler
。
完整示例:https://play.golang.org/p/UHAdxlVdFQQ
两遍方法工作得很好,但是也有mapstructure包的选项,它就是为此而创建的。
从类似的问题中获取答案:使用未知字段解组 JSON,我们可以构造几种方法来在 [] 车辆
数据结构中解组此 JSON 对象。
“手动处理解组”版本可以通过使用通用的< code >[]map[string]interface { } 数据结构,然后从地图切片构建正确的< code>vehicles来完成。为了简单起见,这个例子省略了json包会做的对缺失或错误输入字段的错误检查。
https://play.golang.org/p/fAY9JwVp-4
func NewVehicle(m map[string]interface{}) vehicle {
switch m["type"].(string) {
case "car":
return NewCar(m)
case "plane":
return NewPlane(m)
}
return nil
}
func NewCar(m map[string]interface{}) *car {
return &car{
Type: m["type"].(string),
Color: m["color"].(string),
HP: int(m["hp"].(float64)),
Doors: int(m["doors"].(float64)),
}
}
func NewPlane(m map[string]interface{}) *plane {
return &plane{
Type: m["type"].(string),
Color: m["color"].(string),
Engines: int(m["engines"].(float64)),
}
}
func main() {
var vehicles []vehicle
objs := []map[string]interface{}{}
err := json.Unmarshal(js, &objs)
if err != nil {
log.Fatal(err)
}
for _, obj := range objs {
vehicles = append(vehicles, NewVehicle(obj))
}
fmt.Printf("%#v\n", vehicles)
}
我们可以再次利用json包来处理单个结构的解组和类型检查,方法是第二次直接解组到正确的类型中。这一切都可以通过在[]车辆
类型上定义一个UnmarshalJSON
方法来包装成一个json. Unmarshaler
实现,首先将JSON对象拆分为原始消息。
https://play.golang.org/p/zQyL0JeB3b
type Vehicles []vehicle
func (v *Vehicles) UnmarshalJSON(data []byte) error {
// this just splits up the JSON array into the raw JSON for each object
var raw []json.RawMessage
err := json.Unmarshal(data, &raw)
if err != nil {
return err
}
for _, r := range raw {
// unamrshal into a map to check the "type" field
var obj map[string]interface{}
err := json.Unmarshal(r, &obj)
if err != nil {
return err
}
vehicleType := ""
if t, ok := obj["type"].(string); ok {
vehicleType = t
}
// unmarshal again into the correct type
var actual vehicle
switch vehicleType {
case "car":
actual = &car{}
case "plane":
actual = &plane{}
}
err = json.Unmarshal(r, actual)
if err != nil {
return err
}
*v = append(*v, actual)
}
return nil
}
在java中,不能使用。compareTo()将基元类型(如int)与其他类型进行比较。 如果两个整数小于零,有没有办法比较?我试图将整数与数组中的点进行比较。 谢啦! 解决方法:抱歉,大家都有一秒钟的大脑抽筋。我忘记了a.compareTo(b)根据第一个值是否小于(返回-1)、等于(返回0)或大于(返回1)返回-1、0或1。我的代码是int.compareTo(数组)
问题内容: 由于某些性能原因,我试图找到一种仅选择所选节点中同级节点的方法。例如, 如果选择了inner1节点,是否可以访问其兄弟节点? 问题答案: 好吧…确定…先拜访父母,再拜访孩子。 或者…使用jQuery: 编辑:Cletus一如既往地鼓舞人心。 我进一步挖掘。这就是jQuery本质上如何获得兄弟姐妹的方式:
假设有一个类库X的输入文件,其中包含一些接口。 为了使用这个库,我需要传递一个与。当然,我可以在源文件中创建相同的接口: 但这样一来,我就有了让它和库中的一个保持最新的负担,而且它可能非常大,并导致大量代码重复。 因此,有没有办法“提取”接口的这个特定属性的类型?类似于(这不起作用,导致“找不到名称I2”错误)。 编辑:在TS操场上玩了一会儿后,我注意到以下代码完全实现了我想要的: 但是,它需要声
问题内容: 我想根据一个简单的标准更新一组行,并获取已更改的PK列表。我以为我可以做这样的事情,但担心可能出现的并发问题: 如果将其包装在事务中,是否会发生任何并发问题?还是有更好的方法来做到这一点? 问题答案: 考虑查看OUTPUT子句:
所以我正在做一个需要xml模式的小项目,我对这个模式很不熟悉。 我希望能够设置模式以在两组属性之间进行选择,根据我的研究,这在XSD 1.0中是不可能的,但显然是XSD 1.1的一个特性。 目前我正在使用VisualStudio来完成我的工作,它似乎被困在XSD1.0模式中,这是有意义的,因为XSD1.1显然是一个最新的开发。 我的问题是,是否有一个插件/扩展可以让我在Visual Studio中
我有一个C#类 产品有名称、价格等属性 我想要一个linq查询,它将返回带有产品数组的产品类别的结构,但仅当产品的属性等于一个值时。例如价格是10的地方。 我试过了 但这返回给我一个产品数组,但我想要产品类别中所有符合条件的产品。 作为一个额外的挑战,我也有多个标准,所以在这个例子中,假设价格等于10,30和50。其中一个标准有两个值,这就增加了复杂性。我要做的只是调用不同的选择标准,然后在结尾处