json: cannot unmarshal string into Go struct field .result.case_report of type main.CaseReport

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

json: cannot unmarshal string into Go struct field .result.case_report of type main.CaseReport

问题

我需要对不总是包含某些结构体值的 API 响应进行解组。主结构体的样式如下:

type CaseResponse struct {
	Result struct {
		GroupList               string `json:"group_list"`
		UCopiedFrom             string `json:"u_copied_from"`
		UOfferVariant           string `json:"u_offer_variant"`
		SyncDriver              string `json:"sync_driver"`
		PrimaryContact          *PrimaryContact `json:"primary_contact,omitempty"`
		Entitlement             string          `json:"entitlement"`
		CaseReport              *CaseReport     `json:"case_report,omitempty"`
		ResolvedAt              string          `json:"resolved_at"`
	} `json:"result"`
}

上述 JSON 的内部结构体定义如下:

type PrimaryContact struct {
	Link  string `json:"link,omitempty"`
	Value string `json:"value,omitempty"`
}
type CaseReport struct {
	Link  string `json:"link,omitempty"`
	Value string `json:"value,omitempty"`
}

PrimaryContact 和 CaseReport 经常返回空值,当它们为空时,Go 会抛出错误:json cannot unmarshal string into Go struct .result.case_report of type main.CaseReport

我尝试了一些可能的修复方法。首先,我为内部结构体的值添加了 omitempty,但问题没有解决。然后,我像其他一些帖子中所找到的那样,为 PrimaryContact 和 CaseReport 添加了指针,但当响应返回这些字段没有数据时,我仍然遇到相同的错误,例如:

{
  "result": {
    "group_list": "",
    "u_copied_from": "",
    "u_offer_variant": "",
    "sync_driver": "false",
    "primary_contact":"",
    "entitlement": "",
    "case_report": "",
    "resolved_at": ""
  }
}

但是,当 primary_contact 和 case_report 的值返回如下时,它们可以正常工作:

{
  "result": {
    "group_list": "",
    "u_copied_from": "",
    "u_offer_variant": "",
    "sync_driver": "false",
    "primary_contact": {
      "link": "some link",
      "value": "1e717ed013897b00f2345aa12244b003"
    },
    "entitlement": "",
    "case_report": {
      "link": "some link",
      "value": "2b10fa5e1b1b19d45836ea89bd4bcb35"
    },
    "resolved_at": ""
  }
}

当这些字段没有返回值时,如何安全地解组响应呢?

英文:

I need to unmarshal an API response that not always includes values for some of the structs defined inside the main struct. The main struct looks like this:

type CaseResponse struct {
	Result struct {
		GroupList               string `json:"group_list"`
		UCopiedFrom             string `json:"u_copied_from"`
		UOfferVariant           string `json:"u_offer_variant"`
		SyncDriver              string `json:"sync_driver"`
		PrimaryContact          *PrimaryContact `json:"primary_contact,omitempty"`
		Entitlement             string          `json:"entitlement"`
		CaseReport              *CaseReport     `json:"case_report,omitempty"`
		ResolvedAt              string          `json:"resolved_at"`
	} `json:"result"`
}

The internal structs for above json are defined as:

type PrimaryContact struct {
	Link  string `json:"link,omitempty"`
	Value string `json:"value,omitempty"`
}
type CaseReport struct {
	Link  string `json:"link,omitempty"`
	Value string `json:"value,omitempty"`
}

It is common for PrimaryContact and CaseReport to return empty, and when they do, Go throws error: json cannot unmarshal string into Go struct .result.case_report of type main.CaseReport

I looked for possible fixes. First I added the ",omitempty" to the values for the internal structs, but didn't fix the problem. Then added the pointers for PrimaryContact and CaseReport as found in some other postings, but I'm still hitting the same error when the response comes back with those fields with no data such as:

{
  "result": {
    "group_list": "",
    "u_copied_from": "",
    "u_offer_variant": "",
    "sync_driver": "false",
    "primary_contact":"",
    "entitlement": "",
    "case_report": "",
    "resolved_at": ""
}

but works fine when primary_contact and case_report values come back as:

{
  "result": {
    "group_list": "",
    "u_copied_from": "",
    "u_offer_variant": "",
    "sync_driver": "false",
    "primary_contact": {
      "link": "some link",
      "value": "1e717ed013897b00f2345aa12244b003"
    },
    "entitlement": "",
    "case_report": {
      "link": "some link",
      "value": "2b10fa5e1b1b19d45836ea89bd4bcb35"
    },
    "resolved_at": ""
}

How can the response be safely unmarshal when those fields have no value returned?

答案1

得分: 1

PrimaryContactCaseReport上实现unmarshaler接口。当值为空字符串时不执行任何操作。

func (pc *PrimaryContact) UnmarshalJSON(p []byte) error {
    if string(p) == `""` {
        // 空字符串,不执行任何操作
        return nil
    }
    // 通过声明一个与PrimaryContact具有相同底层类型但没有方法的新类型,防止递归调用此方法。
    type x PrimaryContact
    return json.Unmarshal(p, (*x)(pc))
}

https://go.dev/play/p/UHJobDw5RR2

> Go throws error ...

encoding/json包的函数返回了错误。Go语言没有throw功能。

英文:

Implement the unmarshaler interface on PrimaryContact and CaseReport. Do nothing when the value is the empty string.

func (pc *PrimaryContact) UnmarshalJSON(p []byte) error {
	if string(p) == `""` {
		// empty string, do nothing
		return nil
	}
    // Prevent recursion to this method by declaring a new
    // type with same underlying type as PrimaryContact and
    // no methods. 
	type x PrimaryContact
	return json.Unmarshal(p, (*x)(pc))
}

https://go.dev/play/p/UHJobDw5RR2

> Go throws error ...

The encoding/json package function returned the error. Go does not have the throw feature.

huangapple
  • 本文由 发表于 2022年12月16日 23:57:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/74826862.html
匿名

发表评论

匿名网友

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

确定