Как скопировать повторяющиеся подструктуры из одной структуры в другую? - PullRequest
0 голосов
/ 21 января 2020

У меня есть структура, в которую я распаковал большой XML документ. Я sh, чтобы извлечь определенные элементы из структуры и скопировать их в новую структуру. Однако многие из них являются повторяющимися структурами в другой структуре

Рассмотрим следующий пример (небольшое подмножество всей структуры):

1) Формат данных, поступающих в

type ProductHeader struct {
    Products struct {
        ProductId string `xml:"ProductId"`
        Product   struct {
            PriceBands struct {
                PriceBand []struct {
                    UnitPrice string `xml:"UnitPrice"`
                    LowerQty  string `xml:"LowerQty"`
                    UpperQty  string `xml:"UpperQty"`
                } `xml:"PriceBand"`
            } `xml:"PriceBands"`
        } `xml:"Product"`
    } `xml:"Products"`
}

2) Формат данных I sh для вывода

type ProductOut struct {
    ProductId string `json:"productId"`

    PriceBands struct {
        PriceBand []struct {
            UnitPrice    float32 `json:"unitPrice"`
            LowerQty float32 `json:"lowerQty"`
            UpperQty float32 `json:"upperQty"`
        } `json:"priceBand"`
    } `json:"PriceBands"`
}

Пример XML input

<?xml version="1.0" encoding="utf-8"?>
<ProductHeader>
    <Products xmlns="">
        <ProductId>123XYZ</ProductId>
         <Product>
            <PriceBands>
                <PriceBand>
                    <UnitPrice>25.75</UnitPrice>
                    <LowerQty>0.00</LowerQty>
                    <UpperQty>100.00</UpperQty>
                </PriceBand>
                <PriceBand>
                    <UnitPrice>23.99</UnitPrice>
                    <LowerQty>100.01</LowerQty>
                    <UpperQty>1000.00</UpperQty>
                </PriceBand>
                <PriceBand>
                    <UnitPrice>21.00</UnitPrice>
                    <LowerQty>1000.01</LowerQty>
                    <UpperQty>NULL</UpperQty>
                </PriceBand>
            </PriceBands>
        </Product>
    </Products>
</ProductHeader>

Пример целевого вывода

{
    "productId" : "123XYZ",
    "priceBands" : [ 
        {
            "unitPrice" : 25.75,
            "lowerQty" : 0.00,
            "upperQty" : 100.00
        },
        {
            "unitPrice" : 23.99,
            "lowerQty" : 100.01,
            "upperQty" : 1000.00
        },
        {
            "unitPrice" : 21.00,
            "lowerQty" : 1000.01,
            "upperQty" : null
        }
    ]
}

Как видите, товары могут иметь несколько ценовых диапазонов. Сначала я думал, что просто смогу назначить весь элемент PriceBands в виде:

var p1 ProductHeader
var p2 ProductOut

    p2.PriceBands = p1.Products.Product.PriceBands

Но это дает ошибку компилятора, которая имеет смысл, так как число экземпляров PriceBand является переменным и неизвестным при компиляции время.

Однако это работает, что также имеет смысл:

p2.PriceBands.PriceBand = p1.ProductHeader.PriceBands.PriceBand

Это заставляет меня думать, что мне нужно как-то перебрать структуру PriceBands.

В Python Я мог бы сделать что-то вроде For ProductBand in ProductBands, но этот синтаксис, по-видимому, недоступен в Go.

Как правильно Go перебирать структуру 1) и перемещать ценовые полосы в конкретный экземпляр структуры 2), которую я могу впоследствии распаковать в JSON, как показано в примере вывода выше.

Ответы [ 2 ]

2 голосов
/ 21 января 2020

Попробуйте это:

package main

import (
    "encoding/json"
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "os"
)

type ProductHeaders struct {
    XMLName  xml.Name   `xml:"ProductHeader"`
    Products []Products `xml:"Products"`
}

type Products struct {
    XMLName xml.Name `xml:"Products"`
    Id      string   `xml:"Id"`
    Product Product  `xml:"Product"`
}
type Product struct {
    XMLName    xml.Name   `xml:"Product"`
    PriceBands PriceBands `xml:"PriceBands"`
}
type PriceBand struct {
    XMLName   xml.Name `xml:"PriceBand" json:"-"`
    UnitPrice string   `xml:"UnitPrice" json:"unitPrice"`
    LowerQty  string   `xml:"LowerQty" json:"lowerQty"`
    UpperQty  string   `xml:"UpperQty" json:"upperQty"`
}
type PriceBands struct {
    XMLName   xml.Name    `xml:"PriceBands"`
    PriceBand []PriceBand `xml:"PriceBand"`
}

func main() {

    xmlFile, err := os.Open("/home/prakash/Desktop/demo.xml")
    if err != nil {
        fmt.Println(err)
    }
    defer xmlFile.Close()
    byteValue, _ := ioutil.ReadAll(xmlFile)
    var hdrs ProductHeaders

    out := make(map[string]interface{}) // USING MAP OF INTERFACE
    err = xml.Unmarshal(byteValue, &hdrs)
    if err != nil {
        fmt.Println(err)
    }
    for _, val := range hdrs.Products {
        out["productId"] = val.Id
        data, err := json.Marshal(val.Product.PriceBands.PriceBand)
        // MODIFY THE LOGIC HERE AS PER NEED
        if err != nil {
            fmt.Println(err)
        }
        out["priceBands"] = string(data)
    }
    fmt.Println(out)
    //map[priceBands:[{"unitPrice":"25.75","lowerQty":"0.00","upperQty":"100.00"},{"unitPrice":"23.99","lowerQty":"100.01","upperQty":"1000.00"},{"unitPrice":"21.00","lowerQty":"1000.01","upperQty":"NULL"}] productId:123XYZ]

}

Вот вывод:

map[priceBands:[{"unitPrice":"25.75","lowerQty":"0.00","upperQty":"100.00"},{"unitPrice":"23.99","lowerQty":"100.01","upperQty":"1000.00"},{"unitPrice":"21.00","lowerQty":"1000.01","upperQty":"NULL"}] productId:123XYZ]

2 голосов
/ 21 января 2020

Правильный путь:

  • Разберите входной поток XML в переменную ProductIn in
  • Скопируйте нужные данные из in в ProductOut переменная out, с использованием любого необходимого преобразования, включая for ... range l oop над списками.

Если целое поддерево ProductOut точно соответствует структуре подэлемента дерево ProductIn, то вы можете назначить (например, out.PriceBands = in.ProductHeader.PriceBands) без явного l oop. Предупреждение: объекты in и out теперь совместно используют некоторую память по ссылке (через слайсы), а изменение in может изменить out. Это нормально, если in больше не используется.

В любом случае я вообще не рекомендую использовать отражение для повторяющихся полей, они должны просто отлично преобразовываться в срезы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...