2016-04-20 3 views
0

У меня есть пример json, имена полей не очень важны, но вложенные значения и типы данных некоторых полей. Я понимаю, что в go вы должны убедиться, что при записи в CSV данные являются строковыми типами данных при использовании csv.Writer. Мой вопрос в том, каков надлежащий способ записи вложенных значений, и есть ли эффективный способ преобразования всех значений, отличных от строки, путем итерации через общий json?Преобразование вложенных JSON в csv в GO

`{ 
    "name":"Name1", 
    "id": 2, 
    "jobs":{ 
     "job1":"somejob", 
     "job2":"somejob2" 
    }, 
    "prevIds":{ 
     "id1": 100, 
     "id2": 102 
    } 
}` 

ли пример JSON

+0

Можете ли вы показать нам ожидаемый результат? –

+0

У меня действительно нет ожидаемого результата, но вы хотите посмотреть, как это будет выглядеть с вложенным json. – Nighthee

+0

Вы написали вложенный JSON, так что, я думаю, это ваш ответ? Кажется, вы хотите «преобразовать JSON в csv», но это недостаточно описательно. Как вы хотите, чтобы ваш собственный простой пример выглядел как csv? –

ответ

3

рабочий пример ниже:

package main 

import (
    "encoding/csv" 
    "encoding/json" 
    "fmt" 
    "log" 
    "os" 
    "strconv" 
) 

func decodeJson(m map[string]interface{}) []string { 
    values := make([]string, 0, len(m)) 
    for _, v := range m { 
     switch vv := v.(type) { 
     case map[string]interface{}: 
      for _, value := range decodeJson(vv) { 
       values = append(values, value) 
      } 
     case string: 
      values = append(values, vv) 
     case float64: 
      values = append(values, strconv.FormatFloat(vv, 'f', -1, 64)) 
     case []interface{}: 
      // Arrays aren't currently handled, since you haven't indicated that we should 
      // and it's non-trivial to do so. 
     case bool: 
      values = append(values, strconv.FormatBool(vv)) 
     case nil: 
      values = append(values, "nil") 
     } 
    } 
    return values 
} 

func main() { 
    var d interface{} 
    err := json.Unmarshal(exampleJSON, &d) 
    if err != nil { 
     log.Fatal("Failed to unmarshal") 
    } 
    values := decodeJson(d.(map[string]interface{})) 
    fmt.Println(values) 

    f, err := os.Create("outputfile.csv") 
    if err != nil { 
     log.Fatal("Failed to create outputfile.csv") 
    } 
    defer f.Close() 
    w := csv.NewWriter(f) 
    if err := w.Write(values); err != nil { 
     log.Fatal("Failed to write to file") 
    } 
    w.Flush() 
    if err := w.Error(); err != nil { 
     log.Fatal("Failed to flush outputfile.csv") 
    } 
} 

var exampleJSON []byte = []byte(`{ 
    "name":"Name1", 
    "id": 2, 
    "jobs":{ 
     "job1":"somejob", 
     "job2":"somejob2" 
    }, 
    "prevIds":{ 
     "id1": 100, 
     "id2": 102 
    } 
}`) 

Это работает путем декодирования произвольного JSON, как показано на this goblog post затем итерации и обработки каждого возможного типа путем преобразования его в строка обычным способом. Если вы столкнулись с map[string]interface{}, то вы возвращаетесь, чтобы получить следующий набор данных.

После того, как вы получили []string, вы можете передать его вашему csv.Writer, чтобы выписать, как вам нравится. В этом случае выход

Name1,2,somejob,somejob2,100,102 
+0

AH Я вижу! Спасибо, это очень информативно! Да, я не знал, как обращаться с вложенным объектом. – Nighthee