Возможно ли иметь структуру для динамических ключей вместе со статическими ключами для json в Golang?

Приношу свои извинения за основной вопрос. Я новичок в Golang, и у меня есть json для анализа, как показано ниже

      {
   "config1":{
      "Parameters":{
         "Pm1":"value",
         "Pm2":"value",
         "Pm3":"value"
      },
      "dynamic_key1":{
         "Parameters":{
            "a":"value",
            "b":"value",
            "c":"value",
            "d":"value"
         },
         "Epoch":"value"
      },
      "Epoch":"value"
   }
}

Я пытаюсь написать структуру для анализа этого json и написал структуру следующим образом.

      type Parameters struct {
    Pm1 string `json:"Pm1"`
    Pm2 string `json:"Pm2"`
    Pm3 string `json:"Pm3"`
}

type dynamicParametes struct {
    a string `json:"a"`
    b string `json:"b"`
    c string `json:"c"`
    d string `json:"d"`
}

type dynamic struct {
    Parameters dynamicParametes `json:"Parameters"`
    Epoch      string           `json:"Epoch"`
}

type config1 struct {
    Parameters   Parameters         `json:"Parameters"`
    Dynamic_keys map[string]dynamic `json:"-"`
    Epoch        string             `json:"Epoch"`
}

type config struct {
    config1 config1 `json:"config1"`
}

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

2 ответа

Реализован кастомный демаршлер для типа конфигурации.

Примечание

  • вам нужно открыть все поля в своих структурах, чтобы выполнить демаршалинг json
  • проверьте свою строку json
      type config struct {
    Config1 config1 `json:"config1"`
}

type _config config

func (b *config) UnmarshalJSON(data []byte) error {

    var v = struct {
        Config1 map[string]interface{} `json:"config1"`
    }{}
    if err := json.Unmarshal(data, &v); err != nil {
        return err
    }

    c := _config{}
    err := json.Unmarshal(data, &c)
    if err != nil {
        return err
    }
    
    b.Config1.Parameters = c.Config1.Parameters
    b.Config1.Epoch = c.Config1.Epoch

    if b.Config1.Dynamic_keys == nil {
        b.Config1.Dynamic_keys = map[string]dynamic{}
    }

    for key, config := range v.Config1 {
        if key == `Parameters` || key == `Epoch` {
            continue
        }
        data, err := json.Marshal(config)
        if err != nil {
            return err
        }

        d := dynamic{}
        err = json.Unmarshal(data, &d)
        if err != nil {
            return err
        }
        b.Config1.Dynamic_keys[key] = d
    }

    return nil
}

вы можете увидеть полный код здесь

Все, что вам нужно, это понять, как базовые типы данных выглядят в json.

Поле Parameters в вашем json просто map[string]string и вы можете демаршалировать его с помощью стандартного json.Unmasrhall без какой-либо дополнительной реализации интерфейса json.Unmarshaler.

Ссылка на Go Playground с кодом ниже

      package main

import (
    "encoding/json"
    "fmt"
)

const jsonStr = `{
   "config1":{
      "Parameters":{
         "Pm1":"value_1",
         "Pm2":"value_2",
         "Pm3":"value_3"
      },
      "dynamic_key1":{
         "Parameters":{
            "a":"value_1",
            "b":"value_2",
            "c":"value_3",
            "d":"value_4"
         },
         "Epoch":"value"
      },
      "Epoch":"value"
   }
}`

type Data struct {
    Config1 struct {
        Parameters map[string]string `json:"Parameters"`
        Dynamic    struct {
            Parameters map[string]string `json:"Parameters"`
            Epoch      string            `json:"Epoch"`
        } `json:"dynamic_key1"`
        Epoch string `json:"Epoch"`
    } `json:"config1"`
}

func main() {
    var data Data

    _ = json.Unmarshal([]byte(jsonStr), &data)

    fmt.Printf("%+v\n", data)
}

Выход:

      {Config1:{Parameters:map[Pm1:value_1 Pm2:value_2 Pm3:value_3] Dynamic:{Parameters:map[a:value_1 b:value_2 c:value_3 d:value_4] Epoch:value} Epoch:value}}

Другие вопросы по тегам