如何判断一个键是否在.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?
我认为检查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>);
}