自定义解析 JSON,将两个字段合并

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

Custom unmarshalling json combining two fields

问题

我有一些 JSON 数据,我想要将其解析成以下结构体:

type Activity struct {
    Start time.Time `json:"start"`
    End   time.Time `json:"end"`
}

如果 JSON 格式正确,那么解析是没有问题的。
然而,有时候 "end" 字段存在,但是只是一个空字符串:

{
    "start": "2020-06-02T07:48:35.911Z",
    "end": ""
}

在这种情况下,我想要将 Activity.End 设置为 Activity.Start。
我是否可以通过实现 UnmarshalJSON 来实现这个功能,还是必须使用一个 map?

英文:

I have some json I want to unmarshal into the following struct

type Activity struct {
	Start  time.Time `json:"start"`
    End    time.Time `json:"end"`
}

Works fine if the json is properly formated.
However, sometimes the "end" fields exists but is just an empty string

{
        "start": "2020-06-02T07:48:35.911Z",
        "end":""
}

In this case I want Activity.End = Activity.Start

Is there anyway I can do this by implementing UnmarshalJSON or do I have to use a map?

答案1

得分: 1

根据mkopriva的建议:

package main

import (
	"encoding/json"
	"fmt"
	"time"
)

type Activity struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}

func (a *Activity) UnmarshalJSON(data []byte) error {
	var v struct {
		Start time.Time
		End   json.RawMessage
	}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	if len(v.End) > 0 && string(v.End) != `""` {
		a.Start = v.Start
		return json.Unmarshal([]byte(v.End), &a.End)
	}

	a.Start = v.Start
	a.End = v.Start
	return nil
}

func main() {
	var data1 = []byte(`{"start": "2020-06-02T07:48:35.911Z","end":"2021-10-15T07:48:35.911Z"}`)
	var data2 = []byte(`{"start": "2020-06-02T07:48:35.911Z","end":""}`)

	var a Activity
	if err := json.Unmarshal(data1, &a); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", a)

	if err := json.Unmarshal(data2, &a); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", a)
}

输出结果:

{Start:2020-06-02 07:48:35.911 +0000 UTC End:2021-10-15 07:48:35.911 +0000 UTC}
{Start:2020-06-02 07:48:35.911 +0000 UTC End:2020-06-02 07:48:35.911 +0000 UTC}
英文:

Based on suggestion of mkopriva:

package main

import (
	"encoding/json"
	"fmt"
	"time"
)

type Activity struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}

func (a *Activity) UnmarshalJSON(data []byte) error {
	var v struct {
		Start time.Time
		End   json.RawMessage
	}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	if len(v.End) > 0 && string(v.End) != `""` {
		a.Start = v.Start
		return json.Unmarshal([]byte(v.End), &a.End)
	}
	
	a.Start = v.Start
	a.End = v.Start
	return nil
}

func main() {
	var data1 = []byte(`{"start": "2020-06-02T07:48:35.911Z","end":"2021-10-15T07:48:35.911Z"}`)
	var data2 = []byte(`{"start": "2020-06-02T07:48:35.911Z","end":""}`)

	var a Activity
	if err := json.Unmarshal(data1, &a); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", a)

	if err := json.Unmarshal(data2, &a); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", a)
}

Output:

{Start:2020-06-02 07:48:35.911 +0000 UTC End:2021-10-15 07:48:35.911 +0000 UTC}
{Start:2020-06-02 07:48:35.911 +0000 UTC End:2020-06-02 07:48:35.911 +0000 UTC}

huangapple
  • 本文由 发表于 2021年9月1日 21:26:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/69014656.html
匿名

发表评论

匿名网友

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

确定