簡體   English   中英

如何從 JSON 中將 0 和 false 解組為 bool

[英]How to unmarshall both 0 and false as bool from JSON

目前正在映射服務的輸出,可以說,為其布爾類型自由地交換 0 和 false(以及 1 和 true)。 有沒有辦法為內置的 encoding/json unmarshal 函數使用更寬松的解析器? 我試過在 json 標簽中添加 ,string 無濟於事。

我想要的一個例子:

type MyType struct {
    AsBoolean bool `json:"field1"`
    AlsoBoolean bool `json:"field2"`
}

然后,給定輸入 json:

{
    "field1" : true,
    "field2" : 1
}

結果結構將是:

obj := MyType{}
json_err := json.Unmarshal([]byte(input_json), &obj)
fmt.Printf("%v\n", obj.AsBoolean) //"true"
fmt.Printf("%v\n", obj.AlsoBoolean) //"true"

謝謝 Will Charzuck 的回答,但是,除非我使用指針方法接收器,並在函數體中設置指針的值,否則它對我不起作用。

type ConvertibleBoolean bool

func (bit *ConvertibleBoolean) UnmarshalJSON(data []byte) error {
    asString := string(data)
    if asString == "1" || asString == "true" {
        *bit = true
    } else if asString == "0" || asString == "false" {
        *bit = false
    } else {
        return errors.New(fmt.Sprintf("Boolean unmarshal error: invalid input %s", asString))
    }
    return nil
}

最終使用了特殊的“boolean”類型,而我在使用普通 bool 的地方,換成了這個:

type ConvertibleBoolean bool

func (bit ConvertibleBoolean) UnmarshalJSON(data []byte) error {
    asString := string(data)
    if asString == "1" || asString == "true" {
        bit = true
    } else if asString == "0" || asString == "false" {
        bit = false
    } else {
        return errors.New(fmt.Sprintf("Boolean unmarshal error: invalid input %s", asString))
    }
    return nil
}

這是我的看法。 如果您需要處理一些額外的情況。 根據需要添加更多。

// so you know what's needed.
import (
    "encoding/json"
    "strconv"
    "strings"
)

// NumBool provides a container and unmarshalling for fields that may be
// boolean or numbrs in the WebUI API.
type NumBool struct {
    Val bool
    Num float64
}

// UnmarshalJSON parses fields that may be numbers or booleans.
func (f *NumBool) UnmarshalJSON(b []byte) (err error) {
    switch str := strings.ToLower(strings.Trim(string(b), `"`)); str {
    case "true":
        f.Val = true
    case "false":
        f.Val = false
    default:
        f.Num, err = strconv.ParseFloat(str, 64)
        if f.Num > 0 {
            f.Val = true
        }
    }
    return err
}

操場上看到它。

我也知道這樣的事情:

// FlexBool provides a container and unmarshalling for fields that may be
// boolean or strings in the Unifi API.
type FlexBool struct {
    Val bool
    Txt string
}

// UnmarshalJSON method converts armed/disarmed, yes/no, active/inactive or 0/1 to true/false.
// Really it converts ready, ok, up, t, armed, yes, active, enabled, 1, true to true. Anything else is false.
func (f *FlexBool) UnmarshalJSON(b []byte) error {
    if f.Txt = strings.Trim(string(b), `"`); f.Txt == "" {
        f.Txt = "false"
    }
    f.Val = f.Txt == "1" || strings.EqualFold(f.Txt, "true") || strings.EqualFold(f.Txt, "yes") ||
        strings.EqualFold(f.Txt, "t") || strings.EqualFold(f.Txt, "armed") || strings.EqualFold(f.Txt, "active") ||
        strings.EqualFold(f.Txt, "enabled") || strings.EqualFold(f.Txt, "ready") || strings.EqualFold(f.Txt, "up") ||
        strings.EqualFold(f.Txt, "ok")
    return nil
}

如果你想要真正的小:

// Bool allows 0/1 to also become boolean.
type Bool bool

func (bit *Bool) UnmarshalJSON(b []byte) error {
    txt := string(b)
    *bit = Bool(txt == "1" || txt == "true")
    return nil
}

操場上看到這個。

對於@Twitch Captian 的第三個示例,我發現string(b)的結果導致txt等於""1""而不是我預期的"1" 為了解決這個問題,我將字節數組解組為txt ,然后評估"1" || "true"的內容"1" || "true" "1" || "true"

// Bool allows 0/1 to also become boolean.
type Bool bool

func (bit *Bool) UnmarshalJSON(b []byte) error {
    var txt string
    err := json.Unmarshal(b, &txt)
    if err != nil {
        return err
    }

    *bit = Bool(txt == "1" || txt == "true")
    return nil
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM