首页 > 解决方案 > Golang OpenAPI 3.0 oneOf 构造

问题描述

有没有一种更简洁的方法可以在 Golang 中围绕 oneOf、anyOf、allOf 实现 OpenAPI 3.0 结构。我觉得有一个带有鉴别器字段的平面结构是明智的。(下面的例子)

package main

import (
    "encoding/json"
    "fmt"    
)

type OneOfCertification struct {
    AssetType   string           `json:"assetType"`
    CertDetails *json.RawMessage `json:"certDetails"`
}

type FlatCertification struct {
    AssetType   string   `json:"assetType"`
    DiamondCert *Diamond `json:"diamondCert,omitempty"`
    GemCert     *Gem     `json:"gemCert,omitempty"`
}

type Diamond struct {
    DiamondAttr string `json:"diamondAttr"`
}
type Gem struct {
    GemAttr string `json:"gemAttr"`
}

func oneOfUnmarshalMarshal(data []byte) ([]byte, error) {

    var cert OneOfCertification
    json.Unmarshal(data, &cert)
    switch cert.AssetType {
    case "DIA":
        var dia Diamond
        json.Unmarshal(*cert.CertDetails, &dia)
        fmt.Println("(oneOf) Diamond Cert Details:", dia)

        // Now lets try to Marshal concrete back to raw message
        b, _ := json.Marshal(&dia)
        certDtls := json.RawMessage(b)
        cert.CertDetails = &certDtls
    case "GEM":
        var gem Gem
        json.Unmarshal(*cert.CertDetails, &gem)
        fmt.Println("(oneOf) Gem Cert Details:", gem)

        // Now lets try to Marshal concrete back to raw message
        b, _ := json.Marshal(&gem)
        certDtls := json.RawMessage(b)
        cert.CertDetails = &certDtls

    }

    // Finally Marshal cert and send it back
    return json.Marshal(&cert)
}

func flatUnmarshal(data []byte) ([]byte, error) {
    var cert FlatCertification
    json.Unmarshal(data, &cert)
    switch cert.AssetType {
    case "DIA":
        fmt.Println("(flat) Gem Cert Details:", *cert.DiamondCert)
    case "GEM":
        fmt.Println("(flat) Gem Cert Details:", *cert.GemCert)
    }
    return json.Marshal(&cert)

}

func main() {
    oneOfDiaCert := `{"assetType":"DIA","certDetails":{"diamondAttr":"certified diamond"}}`
    oneOfGemCert := `{"assetType":"GEM","certDetails":{"gemAttr":"certified gem"}}`

    db, _ := oneOfUnmarshalMarshal([]byte(oneOfDiaCert))
    gb, _ := oneOfUnmarshalMarshal([]byte(oneOfGemCert))

    fmt.Println("(oneOf) marshalled diamond certification", string(db))
    fmt.Println("(oneOf) marshalled gem certification", string(gb))

    flatDiaCert := `{"assetType":"DIA","diamondCert":{"diamondAttr":"certified diamond"}}`
    flatGemCert := `{"assetType":"GEM","gemCert":{"gemAttr":"certified gem"}}`

    db, _ = flatUnmarshal([]byte(flatDiaCert))
    gb, _ = flatUnmarshal([]byte(flatGemCert))

    fmt.Println("(flat) marshalled diamond certification", string(db))
    fmt.Println("(flat) marshalled gem certification", string(gb))
}

使用 json.RawMessage 或任何接口 {} 编写的编组和解组的大量代码使它看起来很难看。关于在 Golang 中以更智能的方式实现它的任何想法?

标签: goopenapi

解决方案


推荐阅读