如何判断一个键是否在.net中的反序列化JSON对象中定义过?

本文关键字:反序列化 JSON 对象 定义 net 是否 判断 何判断 一个 | 更新日期: 2023-09-27 18:01:54

我使用c#/。将JSON对象反序列化为本机。NET类型。JSON看起来像:

{
    id: 841,
    runningTime: 33.8643736,
    title: "Test title"
}

…它反序列化到的类看起来像:

public class Slide
{
    public double runningTime
    {
        get;
        set;
    }
    public string title
    {
        get;
        set;
    }
    public int id
    {
        get;
        set;
    }
}

…使用以下代码对其进行反序列化:

// given serializer is an instance of JavaScriptSerializer
var slide = serializer.Deserialize<Slide>(json);

这工作得很好,我可以读取对象上的属性,就像我直接读取JSON一样。

但是,如果title是JSON中的可选键呢?我可以在反序列化后检查它是否为空,但这并不完美,因为title可能在JSON本身中被合法地设置为空,我需要知道键本身是否被定义。使用一些占位符值为title"UNDEFINED"也相当hacky。

所以,如果我使用JavaScriptDeserializer来反序列化JSON,我怎么知道一个键是在JSON中定义的,而不是显式设置为null?

如何判断一个键是否在.net中的反序列化JSON对象中定义过?

我认为检查null是不够的,因为JSON可能包含null。你可以这样写:

public class Slide
{
    public bool HasTitle { get; private set; }
    public double runningTime
    {
        get;
        set;
    }
    private string _title;
    public string title
    {
        get { return _title;  }
        set { _title = value; HasTitle = true; }
    }
    public int id
    {
        get;
        set;
    }
}

现在检查"HasTitle",看看是否设置了标题属性。

在不改变太多代码的情况下,您可以改变定义属性的方式。Nullable<T>为helper结构提供了一个很好的模型,但只适用于值类型。除了没有特殊的编译器和运行时支持(这里不需要)之外,可以很容易地创建一个同样适用于引用类型的版本:

public struct Optional<T>
{
  private readonly bool hasValue;
  private readonly T value;
  public Optional(T value) {
    this.hasValue = true;
    this.value = value;
  }
  public bool HasValue {
    get { return hasValue; }
  }
  public T Value {
    get {
      if (!hasValue)
        throw new InvalidOperationException();
      return value;
    }
  }
  public T GetValueOrDefault() {
    return value;
  }
  public T GetValueOrDefault(T @default) {
    return hasValue ? value : @default;
  }
}

根据需要添加方法

当你有了这个,你就可以改变你的类,把你的属性标记为可选的:

public class Slide
{
  private Optional<double> _runningTime;
  private Optional<string> _title;
  private Optional<int> _id;
  public double runningTime
  {
    get { return _runningTime.GetValueOrDefault(); }
    set { _runningTime = new Optional<double>(value); }
  }
  public string title
  {
    get { return _title.GetValueOrDefault(); }
    set { _title = new Optional<string>(value); }
  }
  public int id
  {
    get { return _id.GetValueOrDefault(); }
    set { _id = new Optional<int>(value);
  }
}

然后可以确定是否调用了属性设置器,并添加对显式取消设置属性的支持:

  public bool IsIdSet() {
    return _id.HasValue;
  }
  public void ResetId() {
    _id = default(Optional<int>);
  }