Skip to content

Instantly share code, notes, and snippets.

@eagletmt
Created April 13, 2020 13:30
Show Gist options
  • Save eagletmt/250e60015555d29badbbcff769a491ee to your computer and use it in GitHub Desktop.
Save eagletmt/250e60015555d29badbbcff769a491ee to your computer and use it in GitHub Desktop.
How to deserialize internally tagged JSON in Go?
{
"items": [
{"type": "A", "foo": "bar"},
{"type": "B", "hoge": "fuga"}
]
}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
)
type Object struct {
Items []json.RawMessage `json:"items"`
}
type ItemA struct {
Type string `json:"type"`
Foo string `json:"foo"`
}
type ItemB struct {
Type string `json:"type"`
Hoge string `json:"hoge"`
}
func main() {
body, err := ioutil.ReadFile("input.json")
if err != nil {
log.Fatal(err)
}
var obj Object
err = json.Unmarshal(body, &obj)
if err != nil {
log.Fatal(err)
}
for _, item := range obj.Items {
var itemA ItemA
var itemB ItemB
if json.Unmarshal(item, &itemA) == nil && itemA.Type == "A" {
fmt.Printf("ItemA %s\n", itemA.Foo)
} else if json.Unmarshal(item, &itemB) == nil && itemA.Type == "B" {
fmt.Printf("ItemB %s\n", itemB.Hoge)
} else {
panic("Unknown item")
}
}
}
#[derive(Debug, serde::Deserialize)]
struct Object {
items: Vec<Item>,
}
#[derive(Debug, serde::Deserialize)]
#[serde(tag = "type")]
enum Item {
A(ItemA),
B(ItemB),
}
#[derive(Debug, serde::Deserialize)]
struct ItemA {
foo: String,
}
#[derive(Debug, serde::Deserialize)]
struct ItemB {
hoge: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = std::fs::File::open("input.json")?;
let obj: Object = serde_json::from_reader(file)?;
for item in obj.items {
match item {
Item::A(item_a) => println!("ItemA {}", item_a.foo),
Item::B(item_b) => println!("ItemB {}", item_b.hoge),
}
}
Ok(())
}
@nekketsuuu
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment