How to unmarshal a field that can be an array or a string in Go?

前端 未结 1 1395
清酒与你
清酒与你 2021-01-29 03:06

I\'m trying to unmarshal this file:

{
  \"@babel/code-frame@7.0.0\": {
    \"licenses\": \"MIT\",
    \"repository\": \"https://github.com/babel/babel/tree/maste         


        
相关标签:
1条回答
  • 2021-01-29 03:52

    Unfortunately, there is no real automatic solution for this provided by the json package.

    But you can unmarshal the dependencies to a map[string]*json.RawMessage instead of map[string]string. json.RawMessage is just a []byte, so you can decide on the type of the message based on the first byte.

    Example:

    for _, value := range dependencies {
        depVal := map[string]*json.RawMessage{}
    
        _ = json.Unmarshal(*value, &depVal)
    
        // check if the first character of the RawMessage is a bracket
        if rune([]byte(*depVal["licenses"])[0]) == '[' {
            var licenses []string
            json.Unmarshal(*depVal["licenses"], &licenses)
            fmt.Println(licenses)
            // do something with the array
        }
    
        result = append(result, Dependency{
            URL:     string(*depVal["repository"]),
            License: string(*depVal["licenses"]),
        })
    }
    

    Another solution would be to use 2 structs. One contains the dependencies as string, the other as array. You can then try to call json.Unmarshal on both of them. Example:

    
    type Dependency struct {
        Licenses string
        // other fields
    }
    
    type DependencyWithArr struct {
        Licenses []string
        // other fields
    }
    
    // in your function
    for _, value := range dependencies {
        type1 := Dependency{}
        type2 := DependencyWithArr{}
    
        err = json.Unmarshal(*value, &type1)
        if err != nil {
            err = json.Unmarshal(*value, &type2)
            // use the array type
        } else {
            // use the single string type
        }
    }
    
    0 讨论(0)
提交回复
热议问题