Go 맵을 json으로 변환


99

encoding/jsonMarshal 을 사용하여 Go 맵을 json 문자열로 변환하려고했지만 빈 문자열이 생성되었습니다.

내 코드는 다음과 같습니다.

package main

import (
    "encoding/json"
    "fmt"
)

type Foo struct {
    Number int    `json:"number"`
    Title  string `json:"title"`
}

func main() {
    datas := make(map[int]Foo)

    for i := 0; i < 10; i++ {
        datas[i] = Foo{Number: 1, Title: "test"}
    }

    jsonString, _ := json.Marshal(datas)

    fmt.Println(datas)
    fmt.Println(jsonString)
}

내 출력은 다음과 같습니다.

map[9:{1 test} 2:{1 test} 7:{1 test} 3:{1 test} 4:{1 test} 5:{1 test} 6:{1 test} 8:{1 test} 0:{1 test} 1:{1 test}]

[]

나는 내가 어디에서 틀렸는 지 정말로 모른다. 도와 주셔서 감사합니다.


32
의견을 남기지 않고 반대표를 던지지 마십시오. 질문이 좋은 질문이라고 생각합니다 (+1) : 모든 코드가 포함되어 있고 정확한 질문과 출력이 포함되어 있습니다. ... 전적으로 주제에 관한 것이고 OP는 좋은 질문을하기 위해 많은 노력을 기울였습니다. 여기에 반대표가 있다는 것은 정말 부끄러운 일입니다!
topskip 2014-07-09

4
문제는 OP가 질문에 즉시 대답했을 오류를 명시 적으로 무시한다는 사실에서 비롯됩니다.
JimB 2014

3
나는 분명히 양심적이었습니다. 한 질문에 두 개의 오류가 있습니다. 내가 반복하지 않을 것임을 확신 할 수 있습니다.
Cronos87

답변:


115

오류를 발견했다면 다음과 같이 보셨을 것입니다.

jsonString, err := json.Marshal(datas)
fmt.Println(err)

// [] json: unsupported type: map[int]main.Foo

문제는 JSON에서 정수를 키로 사용할 수 없다는 것입니다. 금지되어 있습니다. 대신 이러한 값을 사전에 문자열로 변환 할 수 있습니다 (예 : strconv.Itoa.

자세한 내용은이 게시물을 참조하십시오 : https://stackoverflow.com/a/24284721/2679935


3
여기에서 유형이 매핑되는 방식을 볼 수 있습니다 . golang.org/pkg/encoding/json/#Unmarshal 대신 슬라이스를 사용할 수 있으며 이는 JSON 배열에 매핑됩니다. 또한 : 항상 오류 확인;)
seong

2
나는 행동이 바뀌 었다고 생각한다. "지도의 키 유형은 문자열, 정수 유형이거나 encoding.TextMarshaler를 구현해야합니다."에 대해서는 golang.org/pkg/encoding/json/#Unmarshal 을 참조하십시오 .
Ashhar Hasan

@AshharHasan는 분명히 그것은 이동 1.7 (변경 golang.org/doc/go1.7#encoding_json ),하지만 여전히 당신이 무엇을 기대하지 않습니다 play.golang.org/p/0aFaQ_ByOk
julienc

sync.Map으로 이것을 수행하는 방법이 있습니까?
Shahrukh Mohammad

@ShahrukhMohammad 몇 년 동안 Go를 사용하지 않았습니다. 질문에 답할 수 없습니다 ... SO에 대한 새 질문을 만들어보세요!
julienc

27

실제로 무엇이 잘못되었는지 알려주지 만에서 반환 된 오류를 확인하지 않았기 때문에 무시했습니다 json.Marshal.

json: unsupported type: map[int]main.Foo

JSON 사양은 객체 키에 대한 문자열을 제외하고는 아무것도 지원하지 않지만 자바 스크립트는 까다 롭지 않지만 여전히 불법입니다.

두 가지 옵션이 있습니다.

1 map[string]Foo색인을 사용 하고 문자열로 변환합니다 (예 : fmt. Sprint 사용).

datas := make(map[string]Foo, N)

for i := 0; i < 10; i++ {
    datas[fmt.Sprint(i)] = Foo{Number: 1, Title: "test"}
}
j, err := json.Marshal(datas)
fmt.Println(string(j), err)

2 간단히 슬라이스 (자바 스크립트 배열)를 사용합니다.

datas2 := make([]Foo, N)
for i := 0; i < 10; i++ {
    datas2[i] = Foo{Number: 1, Title: "test"}
}
j, err = json.Marshal(datas2)
fmt.Println(string(j), err)

playground


4
네가 옳아. 부끄러운 오류입니다. json 키에 int를 사용하는 이유를 모르겠습니다. 예를 들어 주셔서 감사합니다.
Cronos87 2014

2

이 질문에 대한 질문 / 마지막 답변 이후, 여기 에서 TextMarshalerTextUnmarshaler 인터페이스를 사용하여 json Marshal / UnMarshal의 맵에 대한 비 문자열 키 유형에 대한 지원이 추가되었습니다 . 키 유형에 대해 이러한 인터페이스를 구현하면 예상대로 작동합니다.json.Marshal

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

// Num wraps the int value so that we can implement the TextMarshaler and TextUnmarshaler 
type Num int

func (n *Num) UnmarshalText(text []byte) error {
    i, err := strconv.Atoi(string(text))
    if err != nil {
        return err
    }
    *n = Num(i)
    return nil
}

func (n Num) MarshalText() (text []byte, err error) {
    return []byte(strconv.Itoa(int(n))), nil
}

type Foo struct {
    Number Num    `json:"number"`
    Title  string `json:"title"`
}

func main() {
    datas := make(map[Num]Foo)

    for i := 0; i < 10; i++ {
        datas[Num(i)] = Foo{Number: 1, Title: "test"}
    }

    jsonString, err := json.Marshal(datas)
    if err != nil {
        panic(err)
    }

    fmt.Println(datas)
    fmt.Println(jsonString)

    m := make(map[Num]Foo)
    err = json.Unmarshal(jsonString, &m)
    if err != nil {
        panic(err)
    }

    fmt.Println(m)
}

산출:

map[1:{1 test} 2:{1 test} 4:{1 test} 7:{1 test} 8:{1 test} 9:{1 test} 0:{1 test} 3:{1 test} 5:{1 test} 6:{1 test}]
[123 34 48 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 49 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 50 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 51 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 52 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 53 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 54 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 55 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 56 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 57 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 125]
map[4:{1 test} 5:{1 test} 6:{1 test} 7:{1 test} 0:{1 test} 2:{1 test} 3:{1 test} 1:{1 test} 8:{1 test} 9:{1 test}]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.