Условные (динамические) структурные теги - PullRequest
0 голосов
/ 26 мая 2019

Я пытаюсь разобрать некоторые документы XML в Go.Для этого мне нужно определить несколько структур, и мои теги struct зависят от определенного условия.

Представьте себе следующий код (хотя я знаю, что он не будет работать)

if someCondition {
    type MyType struct {
        // some common fields
        Date    []string `xml:"value"`
    }
} else {
    type MyType struct {
        // some common fields
        Date    []string `xml:"anotherValue"`
    }
}

var t MyType
// do the unmarshalling ...

Проблема в том, что эти две структуры имеют много общих полей.Разница лишь в одном из полей, и я хочу предотвратить дублирование.Как я могу решить эту проблему?

Ответы [ 3 ]

2 голосов
/ 26 мая 2019

Вы используете различные типы для демаршалирования.По сути, вы пишете код демаршаллинга дважды и запускаете либо первую версию, либо вторую.Для этого нет динамического решения.

0 голосов
/ 27 мая 2019

Как уже указывалось, вы должны продублировать поле.Вопрос в том, где должно существовать дублирование.

Если это всего лишь одно поле из множества, одним из вариантов является использование встраивания и затенения полей:

type MyType struct {
    Date    []string `xml:"value"`
    // many other fields
}

Тогда, когда Date используетдругое имя поля:

type MyOtherType struct {
    MyType // Embed the original type for all other fields
    Date     []string `xml:"anotherValue"`
}

Затем после демаршалирования MyOtherType легко переместить значение Date в исходную структуру:

type data MyOtherType
err := json.Unmarshal(..., &data)
data.MyType.Date = data.Date
return data.MyType // will of MyType, and fully populated

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

0 голосов
/ 26 мая 2019

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

Например:

type MyType struct {
    DateField1    []string `xml:"value"`
    DateField2    []string `xml:"anotherValue"`
}

// After parsing, you have two options:

// Option 1: re-assign one field onto another:
if !someCondition {
    parsed.DateField1 = parsed.DateField2
    parsed.DateField2 = nil
}

// Option 2: use the above as an intermediate struct, the final being:
type MyFinalType struct {
    Date    []string `xml:"value"`
}

if someCondition {
    final.Date = parsed.DateField1
} else {
    final.Date = parsed.DateField2
}

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

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