在Go语言中,当解析类似的JSON数据时,应避免代码重复。

huangapple go评论82阅读模式
英文:

Avoid Code Duplication when unmarshalling similar json in go

问题

我正在努力想出一种优雅的方法来消除Go语言中的代码重复。ReadImageDataJsonreadJSON函数基本上是相同的,只是它们返回不同的JSON格式。

package artworks

import (
	"encoding/json"
	"io/ioutil"
	"log"
)

type Artworks struct {
	Artist         string `json:"artist"`
	Tags           string `json:"tags"`
	Id             string `json:"id"`
	Thumbnail      string `json:"thumbnail"`
	High_res_image string `json:"high_res_image"`
	Date_uploaded  string `json:"date_uploaded"`
	Url            string `json:"url"`
}

type ArtworksWithImageData struct {
	Artworks
	Imagedata string `json:"image_data"`
}

func ReadImageDataJson(filePath string) []ArtworksWithImageData {
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
	}
	var artworkData []ArtworksWithImageData
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
	}
	return artworkData
}

func readJSON(filePath string) []Artworks {
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
	}
	var artworkData []Artworks
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
	}
	return artworkData
}

我已经写出了如下代码:

func readJSON[T []Artworks | []ArtworksWithImageData](filePath string, jsonFormat T) T {
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
	}
	var artworkData T
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
	}
	return artworkData
}

但我不确定它是否真正有效,因为当我调用它时,例如readJson("myfile.json", []Artworks]),我会得到错误[]Artworks (type) is not an expression

英文:

I'm struggling to come up with an elegant way of eliminating code duplication in Go. The ReadImageDataJson and readJSON functions are basically the same except they return different json formats.

package artworks

import (
	"encoding/json"
	"io/ioutil"
	"log"
)

type Artworks struct {
	Artist         string `json:"artist"`
	Tags           string `json:"tags"`
	Id             string `json:"id"`
	Thumbnail      string `json:"thumbnail"`
	High_res_image string `json:"high_res_image"`
	Date_uploaded  string `json:"date_uploaded"`
	Url            string `json:"url"`
}

type ArtworksWithImageData struct {
	Artworks
	Imagedata string `json:"image_data"`
}

func ReadImageDataJson(filePath string) []ArtworksWithImageData {
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
	}
	var artworkData []ArtworksWithImageData
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
	}
	return artworkData
}

func readJSON(filePath string) []Artworks {
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
	}
	var artworkData []Artworks
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
	}
	return artworkData
}

I've got so far as writing this out:

func readJSON[T []Artworks | []ArtworksWithImageData](filePath string, jsonFormat T) T {
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
	}
	var artworkData T
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
	}
	return artworkData
}

But I'm not sure it really works because when I call it, i.e. readJson("myfile.json", []Artworks]) I get the error []Artworks (type) is not an expression

答案1

得分: 1

实际上,我刚刚弄清楚了!只需要在标签中添加omitempty

type Artworks struct {
	Artist         string `json:"artist"`
	Tags           string `json:"tags"`
	Id             string `json:"id"`
	Thumbnail      string `json:"thumbnail"`
	High_res_image string `json:"high_res_image"`
	Date_uploaded  string `json:"date_uploaded"`
	Url            string `json:"url"`
	Imagedata      string `json:"image_data,omitempty"`
}


func readJSON(filePath string) []Artworks {
    artworksList, error := ioutil.ReadFile(filePath)
    if error != nil {
        log.Fatalf("Error when opening file: %v", error.Error())
    }
    var artworkData []Artworks
    error = json.Unmarshal(artworksList, &artworkData)
    if error != nil {
        log.Fatalf("Error during unmarshal(): %v", error.Error())
    }
    return artworkData
}

我还发现,如果你使用的是 Go 版本大于 1.18,你可以使用泛型来实现这个:

func readJSONGeneric[T Artwork | ArtworkWithImageData](filePath string) (T, error) {
	var artworkData T
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
		return artworkData, error
	}
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
		return artworkData, error

	}
	return artworkData, nil
}
英文:

Actually think I just figured this out! Just had to add omitempty to the tag.

type Artworks struct {
	Artist         string `json:"artist"`
	Tags           string `json:"tags"`
	Id             string `json:"id"`
	Thumbnail      string `json:"thumbnail"`
	High_res_image string `json:"high_res_image"`
	Date_uploaded  string `json:"date_uploaded"`
	Url            string `json:"url"`
	Imagedata      string `json:"image_data,omitempty"`
}


func readJSON(filePath string) []Artworks {
    artworksList, error := ioutil.ReadFile(filePath)
    if error != nil {
        log.Fatalf("Error when opening file: %v", error.Error())
    }
    var artworkData []Artworks
    error = json.Unmarshal(artworksList, &artworkData)
    if error != nil {
        log.Fatalf("Error during unmarshal(): %v", error.Error())
    }
    return artworkData
}

I also figured out you can do this with generics if you're on go > 1.18:

func readJSONGeneric[T Artwork | ArtworkWithImageData](filePath string) (T, error) {
	var artworkData T
	artworksList, error := ioutil.ReadFile(filePath)
	if error != nil {
		log.Fatalf("Error when opening file: %v", error.Error())
		return artworkData, error
	}
	error = json.Unmarshal(artworksList, &artworkData)
	if error != nil {
		log.Fatalf("Error during unmarshal(): %v", error.Error())
		return artworkData, error

	}
	return artworkData, nil
}

huangapple
  • 本文由 发表于 2023年3月22日 08:58:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75807619.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定