我想将各种对象编码到文件中,然后解码它们,并通过获取编码的变量类型将它们转换回它们的原始类型。 关键是我想将未编码的对象转换为指定变量的类型,而不指定类型。
简短的伪代码:
// Marshal this
item := Book{"The Myth of Sisyphus", "Albert Camus"}
// Then unmarshal and convert to the type of the item variable.
itemType := reflect.TypeOf(item)
newItem itemType = unmarshalledItem.(itemType) // This is the problem.
fmt.Println("Unmarshalled is:", reflect.TypeOf(newItem)) // Should print *main.Book
完整代码:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"reflect"
)
type Book struct {
Title string
Author string
}
func main() {
// Create objects to marshal.
book := Book{"The Myth of Sisyphus", "Albert Camus"}
box := make(map[string]interface{})
box["The Myth of Sisyphus"] = &book
itemType := reflect.TypeOf(box["The Myth of Sisyphus"])
fmt.Println("Book is:", itemType)
// Marshal objects to file.
err := Write(&book)
if err != nil {
fmt.Println("Unable to save store.", err)
return
}
// Unmarshal objects from file.
untyped := make(map[string]interface{})
bytes, err := ioutil.ReadFile("store.txt")
if err != nil {
fmt.Println("Unable to load store.", err)
return
}
err = json.Unmarshal(bytes, &untyped)
if err != nil {
fmt.Println("Err in store unmarshal.", err)
return
}
// Get Title property of unmarshalled object,
// and use that to get variable type from box map.
for k, v := range untyped {
if k == "Title" {
itemTitle := v.(string)
fmt.Println("Cast item having title:", itemTitle)
targetType := reflect.TypeOf(box[itemTitle])
fmt.Println("Type to cast to is:", targetType)
// Convert untyped to targetType.
// This is the problem.
typed targetType = untyped.(targetType)
fmt.Println("Unmarshalled is:", reflect.TypeOf(typed)) // Should print *main.Book
}
}
}
func Write(b *Book) error {
data, err := json.Marshal(b)
if err != nil {
return err
}
newFilename := "store.txt"
f, err := os.OpenFile(newFilename, os.O_CREATE|os.O_TRUNC, 0660)
if err != nil {
return err
}
_, err = f.WriteString(string(data) + "\n")
if err != nil {
return err
}
return nil
}
最佳答案
这可能适用于动态类型的语言,但在这里行不通,因为 Go 是静态类型的。
这本书不是作为 Book 存储的,而是作为 json 字符串存储的,json unmarshaller 不知道它是 Book,除非你告诉它。即它不知道将字段映射到 Book 对象。
你不能将未编码的“untyped”转换成一本书,因为它不是一本书,它是一个 map[string]interface{},恰好看起来完全像一本书。
你需要做的是
- 将 json 解码为 map[string]interface{},然后读取标题。
- 根据类型使用 if 语句或 switch 语句
- 再次将 json 解码为该类型的对象(例如,一本书)
我猜是这样的:
// check the type
if targetType.String() == "*main.Book" {
// unmarshall it again as a Book
var typedBook Book
_ = json.Unmarshal(bytes, &typedBook)
fmt.Println("Unmarshalled is:", reflect.TypeOf(typedBook)) // Should print *main.Book
} else if targetType.String() == "*main.Magazine" {
// unmarshal a magazine or whatever
}
关于casting - 如何将未编码的 Golang 对象转换为指定变量的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26567249/