将XML属性解析到接口中的Golang unmarshal

3
我正在尝试将一些XML解包成一个具有interface{}类型的结构体。然而,无论何时我试图运行它,代码都无法获取任何东西。所有其他元素似乎都正常工作,如果我将类型设置为string或[]byte,它将起作用,但是我需要它更加灵活。
我的兴趣所在的元素位于第32行 - FloorRefID
链接:https://play.golang.org/p/Ehr8qx1aWf
<?xml version="1.0" encoding="UTF-8"?>
    <Locations totalPages="1" currentPage="1" pageSize="25">
       <WirelessClientLocation macAddress="00:00:00:00:00:00">
          <MapInfo mapHierarchyString="Head office&gt;Ground floor&gt;Store" floorRefId="-1122334455667789">
             <Image imageName="floorPlan1.png" />
          </MapInfo>
          <MapCoordinate x="2850" y="3000" unit="FEET" />
       </WirelessClientLocation>
       <WirelessClientLocation macAddress="11:11:11:11:11:11">
          <MapInfo mapHierarchyString="Head office&gt;Ground floor&gt;Store" floorRefId="-1122334455667789">
            <Image imageName="floorPlan1.png" />
          </MapInfo>
          <MapCoordinate x="10.72" y="76.49" unit="FEET" />
       </WirelessClientLocation>
       <WirelessClientLocation macAddress="26:cd:96:46:0b:2b">
          <MapInfo floorRefId="0" />
          <MapCoordinate x="51.52" y="4.2" unit="FEET" />
       </WirelessClientLocation>
    </Locations>

给一些背景信息;我正在负责一个与供应商集成的项目,在这个项目中,有时我们会收到XML格式的数据,有时会收到JSON格式的数据。我希望构建一个能够解析两种结构的东西,而不是复制这个结构集。它有许多子结构,这意味着需要更多的工作来维护两个几乎相同但具有不同属性的结构。
当我们收到JSON数据时,字段可以是字符串或数字。
我已经阅读过不能将接口解封(unmarshal)的文章,但是否有人知道如何解决我的这种情况?

请在问题本身中包含您的Go代码,而不是链接到它。 - Adrian
1个回答

5

始终检查返回的错误信息非常重要。

if err := xml.Unmarshal([]byte(xmlRawData), &xmlData); err != nil {
    fmt.Println(err)
}

你收到的错误是:
cannot unmarshal into interface {}

由于空接口没有任何导出字段用于映射 XML 键/值,因此无法取消编组空接口。

但是,有一个方法可以解决这个问题。在您的 VendorMapInfo 结构上实现xml.Unmarshaler 接口。

示例:您更新后的代码

type VendorMapInfo struct {
    MapHierarchyString string      `xml:"mapHierarchyString,attr"`
    FloorRefID         interface{} `xml:"floorRefId,attr"`
    Image              Image       `xml:"Image"`
    FloorDimension     VendorFloorDimension
}

type Image struct {
    Name string `xml:"imageName,attr"`
}

func (mf *VendorMapInfo) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    // Attributes
    for _, attr := range start.Attr {
        switch attr.Name.Local {
        case "mapHierarchyString":
            mf.MapHierarchyString = attr.Value
        case "floorRefId":
            mf.FloorRefID = findFloorRefIDType(attr.Value)
        }
    }

    for {
        token, err := d.Token()
        if err != nil {
            return err
        }

        switch el := token.(type) {
        case xml.StartElement:
            if el.Name.Local == "Image" {
                item := new(Image)
                if err = d.DecodeElement(item, &el); err != nil {
                    return err
                }
                mf.Image = *item
            }
        case xml.EndElement:
            if el == start.End() {
                return nil
            }
        }
    }

    return nil
}

完整代码,游戏链接:https://play.golang.org/p/wZQOsQv0Nq

输出结果:

{Locations:{Space: Local:} WirelessClientLocation:[{MacAddress:00:00:00:00:00:00 MapInfo:{MapHierarchyString:Head office>Ground floor>Store FloorRefID:-1122334455667789 Image:{Name:floorPlan1.png} FloorDimension:{Length:0 Width:0 Height:0 OffsetX:0 OffsetY:0 Unit:}}} {MacAddress:11:11:11:11:11:11 MapInfo:{MapHierarchyString:Head office>Ground floor>Store FloorRefID:-1122334455667789 Image:{Name:floorPlan1.png} FloorDimension:{Length:0 Width:0 Height:0 OffsetX:0 OffsetY:0 Unit:}}} {MacAddress:26:cd:96:46:0b:2b MapInfo:{MapHierarchyString: FloorRefID:0 Image:{Name:} FloorDimension:{Length:0 Width:0 Height:0 OffsetX:0 OffsetY:0 Unit:}}}]}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接