duanlun2827 2018-08-23 11:50
浏览 359

Golang OpenAPI 3.0 oneOf构造

Is there a cleaner way to implement OpenAPI 3.0 constructs around oneOf, anyOf, allOf in Golang. I feel that it would be wise to have a flat structure with a discriminator field. (example below)

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))
}

The sheer amount of code written to marshal and unmarshal with json.RawMessage or any interface {} makes it look ugly. Any thoughts on implementing it in a smarter fashion in Golang ??

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 SQL Server下载
    • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
    • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
    • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?
    • ¥15 python爬取bilibili校园招聘网站
    • ¥30 求解达问题(有红包)
    • ¥15 请解包一个pak文件
    • ¥15 不同系统编译兼容问题
    • ¥100 三相直流充电模块对数字电源芯片在物理上它必须具备哪些功能和性能?
    • ¥30 数字电源对DSP芯片的具体要求