Атрибут XML Unmarshalling по-разному в случае массивов в Golang - PullRequest
0 голосов
/ 14 марта 2019

У меня есть веб-сервис, где я ожидаю получить два разных запроса; один называется Request, содержащий только один Request, а другой - RequestBulk, который содержит массив Request с. Оба сопоставлены с Голангом следующим образом:

type RequestBulk struct {
    XMLName  xml.Name  `xml:"https://item.com RequestBulk"`
    Message  string    `xml:"Message"`
    Request  []Request `xml:"Request,omitempty"`
}

type Request struct {
    XMLName xml.Name `xml:"https://item.com Request"`
    Text    string   `xml:"text"`
}

Отмена сортировки следующих XML-файлов работает должным образом:

<Request xmlns="https://item.com">
  <text>Some request text</text>
</Request>
<RequestBulk xmlns="https://item.com">
  <Message>Some Text</Message>
  <Request xmlns="https://item.com">
    <text>Some request text</text>
  </Request>
  <Request xmlns="https://item.com">
    <text>Some other request text</text>
  </Request>
</RequestBulk>

Проблема

В RequestBulk, если я изменю

Request []Request `xml:"Request,omitempty"`

до

RequestMessage []Request `xml:"RequestMessage,omitempty"`

и измените XML на:

<RequestBulk xmlns="https://item.com">
  <Message>Some Text</Message>
  <RequestMessage xmlns="https://item.com">
    <text>Some request text</text>
  </RequestMessage>
  <RequestMessage xmlns="https://item.com">
    <text>Some other request text</text>
  </RequestMessage>
</RequestBulk>

Я получаю следующую ошибку:

ожидаемый тип элемента , но есть

Очевидно, из-за XMLName xml.Name `xml:"https://item.com Request"`

Вопрос

Как сохранить структуру Request без изменений и по-прежнему принимать сообщения типа RequestBulk с другим именем для структуры Request, а именно RequestMessage?

Другими словами; Как использовать одну и ту же структуру с разными пространствами имен?


Запустите его на Игровая площадка Go .

1 Ответ

1 голос
/ 14 марта 2019

Вы можете реализовать интерфейс Unmarshaler для перезаписи локального имени элемента перед передачей элемента в декодер для фактического демаршалинга.

func (r *Request) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    if start.Name.Local == "RequestMessage" {
        start.Name.Local = "Request" // overwrite
    }
    type tmp Request // avoid infinite recursive calls to Request.UnmarshalXML
    return d.DecodeElement((*tmp)(r), &start) // unmarshal
}

https://play.golang.org/p/0a_gpgkywwf

...