Как выровнять вложенную структуру JSON в го - PullRequest
0 голосов
/ 17 сентября 2018

Я получаю вложенные данные из Монго и хочу выровнять их в структуре, чтобы сохранить их в CSV-файле.

Данные выглядят так:

{
    "_id" : "bec7bfaa-7a47-4f61-a463-5966a2b5c8ce",
    "data" : {
        "driver" : {
            "etaToStore" : 156
        },
        "createdAt" : 1532590052,
        "_id" : "07703a33-a3c3-4ad5-9e06-d05063474d8c"
    }
} 

Иструктура, которую я хочу получить, должна выглядеть примерно так:

type EventStruct struct {
    Id                  string      `bson:"_id"`
    DataId              string      `bson:"data._id"`
    EtaToStore          string      `bson:"data.driver.etaToStore"`
    CreatedAt           int         `bson:"data.createdAt"`
}

Это не работает, поэтому после некоторых ответов SO Я разбил его на несколько структур:

// Creating a structure for the inner struct that I will receive from the query
type DriverStruct struct {
    EtaToStore  int     `bson:"etaToStore"`
}

type DataStruct struct {
    Id          string `bson:"_id"`
    Driver      DriverStruct `bson:"driver"`
    CreatedAt   int `bson:"createdAt"`
}
// Flattenning out the structure & getting the fields we need only
type EventStruct struct {
    Id                  string      `bson:"_id"`
    Data                DataStruct  `bson:"data"`
}

Это получает все данные из результата запроса Mongo, но оно вложено:

{
  "Id": "bec7bfaa-7a47-4f61-a463-5966a2b5c8ce",
  "Data": {
     "Id": a33-a3c3-4ad5-9e06-d05063474d8c,
     "Driver": {
        "EtaToStore": 156
     },
     "CreatedAt": 1532590052
  }
}

В итоге я хочу получить следующее:

{
  "Id": "bec7bfaa-7a47-4f61-a463-5966a2b5c8ce",
  "DataId": "a33-a3c3-4ad5-9e06-d05063474d8c",
  "EtaToStore": 156,
  "CreatedAt": 1532590052
}

Я уверенЕсть простой способ сделать это, но я не могу понять это, помогите!

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Вы можете реализовать интерфейс json.Unmarshaler, чтобы добавить пользовательский метод для демонтажа json. Затем в этом методе вы можете использовать вложенный структурный формат, но вернуть сглаженный в конце.

func (es *EventStruct) UnmarshalJSON(data []byte) error {
    // define private models for the data format

    type driverInner struct {
        EtaToStore int `bson:"etaToStore"`
    }

    type dataInner struct {
        ID        string      `bson:"_id" json:"_id"`
        Driver    driverInner `bson:"driver"`
        CreatedAt int         `bson:"createdAt"`
    }

    type nestedEvent struct {
        ID   string    `bson:"_id"`
        Data dataInner `bson:"data"`
    }

    var ne nestedEvent

    if err := json.Unmarshal(data, &ne); err != nil {
        return err
    }

    // create the struct in desired format
    tmp := &EventStruct{
        ID:         ne.ID,
        DataID:     ne.Data.ID,
        EtaToStore: ne.Data.Driver.EtaToStore,
        CreatedAt:  ne.Data.CreatedAt,
    }

    // reassign the method receiver pointer
    // to store the values in the struct
    *es = *tmp
    return nil
}

Пример запуска: https://play.golang.org/p/83VHShfE5rI

0 голосов
/ 17 сентября 2018

Вы можете использовать в основном ту же логику, что и:

package utils

// FlattenIntegers flattens nested slices of integers
func FlattenIntegers(slice []interface{}) []int {
    var flat []int

    for _, element := range slice {
        switch element.(type) {
        case []interface{}:
            flat = append(flat, FlattenIntegers(element.([]interface{}))...)
        case []int:
            flat = append(flat, element.([]int)...)
        case int:
            flat = append(flat, element.(int))
        }
    }

    return flat
}

(Источник: https://gist.github.com/Ullaakut/cb1305ede48f2391090d57cde355074f)

Приспосабливая это к тому, что находится в вашем JSON. Если вы хотите, чтобы он был универсальным, вам нужно будет поддерживать все типы, которые он может содержать.

...