【问题标题】:How to Marshall any data type to string and Unmarshal from string to specific data type on condition如何根据条件将任何数据类型编组为字符串并从字符串解组为特定数据类型
【发布时间】:2020-12-23 06:50:18
【问题描述】:
type State struct {
    Type      string    `json:"type" validate:"required"`
    Value     string    `json:"value"`
}

我有一个这样的结构。我需要将不同类型的状态传递给 API。

例如:状态可以是{ type : 'boolean', value: true }{ type : 'string', value: 'ABC' }

我将它( value )作为字符串存储在 db 中。

然后,当我从 API 传递时,我需要考虑类型(而不是字符串)来设置特定值。

和这个{ type : 'boolean', value: true }{ type : 'string', value: 'ABC' }一样

我如何通过编组和解组来实现这一点?

【问题讨论】:

    标签: json go struct marshalling unmarshalling


    【解决方案1】:

    您可以在代码中定义编组和解组逻辑。

    type State struct {
        Type  string      `json:"type" validate:"required"`
        Value interface{} `json:"value"`
    }
    
    func (s *State) UnmarshalJSON(b []byte) (err error) {
        tmpMap := map[string]string{}
        err = json.Unmarshal(b, &tmpMap)
        if err != nil {
            return err
        }
        if tmpMap["type"] == "" {
            return errors.New("type not present")
        }
        if tmpMap["value"] == "" {
            return errors.New("value not present")
        }
        if tmpMap["type"] == "string" {
            s.Type = "string"
            s.Value = tmpMap["value"]
        } else if tmpMap["type"] == "boolean" {
            s.Type = "boolean"
            s.Value = tmpMap["value"] == "true"
        } else {
            //TODO implements other type
            return errors.New(fmt.Sprintf("Unknown type %s", tmpMap["type"]))
        }
        return nil
    }
    

    https://play.golang.org/p/BnD7HAuURzJ

    同样,您可以在State struct 上定义MarshalJSON 方法来处理数据序列化。

    func (c State) MarshalJSON() ([]byte, error)

    要将State db 存储在 db 的单列中,您可以实现

    func (c State) Value() (driver.Value, error)

    要从 DB 列构建状态,您需要将 Scan 方法实现为

    func (e *State) Scan(value interface{}) error

    【讨论】:

    • 我有点困惑。如果在编组和解组中我们正在进行类型转换,为什么我们还需要实现自定义Value()Scan()?无论如何,谢谢,我会试试这个。
    • 由于驱动程序/lib 不知道自定义转换,因此没有将字符串转换为某些特定数据类型的自动机制。
    • 知道了。我对这个 UnmarshalJSON 有点困惑。在这里它正在检查 s.Value = tmpMap["value"] == "true" ,当我通过这个 {"type":"boolean", "value": "false"} 时它可以工作。但我希望它通过这个 to API {"type":"boolean", "value": false} 和相同的 from API
    • 没问题,这种情况下不需要UnmarshalJSON方法,它可以自动检测数据类型。
    猜你喜欢
    • 2021-12-22
    • 2015-02-08
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-06
    • 1970-01-01
    • 2015-10-23
    相关资源
    最近更新 更多