【问题标题】:How to call json.Unmarshal inside UnmarshalJSON without causing stack overflow?如何在 UnmarshalJSON 中调用 json.Unmarshal 而不会导致堆栈溢出?
【发布时间】:2019-08-29 00:59:11
【问题描述】:

如何在结构中创建方法 UnmarshalJSON,在内部使用 json.Unmarshal 而不会导致堆栈溢出?

package xapo

type Xapo struct {}

func (x Xapo) UnmarshalJSON(data []byte) error {
    err := json.Unmarshal(data, &x)
    if err != nil {
        return err
    }
    fmt.Println("done!")
    return nil
}

谁能解释一下为什么会发生堆栈溢出?可以修吗?

提前致谢。

【问题讨论】:

  • 函数的用途是什么?
  • json.Unmarshal 将识别&x 的类型并最终再次调用x.UnmarshalJSON 等等。我认为这可以通过一些额外的类型层来解决,但这完全取决于你为什么需要这个.

标签: go struct


【解决方案1】:

您似乎正在尝试通过使用默认解组器然后对数据进行后处理来进行自定义解组。但是,正如您所发现的,尝试这样做的明显方式会导致无限循环!

通常的解决方法是使用您的类型创建一个新类型,在新类型的实例上使用默认解组器,对数据进行后处理,然后最终转换为原始类型并分配回目标实例。请注意,您需要在指针类型上实现 UnmarshalJSON。

例如:

func (x *Xapo) UnmarshalJSON(data []byte) error {
  // Create a new type from the target type to avoid recursion.
  type Xapo2 Xapo

  // Unmarshal into an instance of the new type.
  var x2 Xapo2
  err := json.Unmarshal(data, &x2)
  if err != nil {
    return err
  }

  // Perform post-processing here.
  // TODO

  // Cast the new type instance to the original type and assign.
  *x = Xapo(x2)
  return nil
}

【讨论】:

  • 不错!我将不得不在我的代码中更新我的劣质解决方案以匹配别名。预别名,我创建了一个具有相同结构的本地匿名结构。结构从未改变,谢天谢地,但现在我不必担心它会这样做。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-02-09
  • 2012-09-18
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 2020-12-17
相关资源
最近更新 更多