我如何判断是否曾在 .NET 的反序列化 JSON 对象中定义过键?
How can I tell if a key was ever defined in a deserialized JSON object in .NET?
我正在使用 C#/.NET 4.5 将 JSON 对象反序列化为本机 .NET 类型。 JSON 看起来像:
{
id: 841,
runningTime: 33.8643736,
title: "Test title"
}
...它反序列化后的 class 看起来像:
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 中的可选键呢?我可以在反序列化后检查它是否为 null,但这并不完美,因为 title
可以在 JSON 本身中合法地设置为 null,我需要知道密钥本身是否已定义。为 title
使用一些占位符值,例如 "UNDEFINED"
也很老套。
所以,如果我使用 JavaScriptDeserializer
来反序列化 JSON,我如何判断一个键是否首先在 JSON 中定义与显式设置为无效?
无需过多更改其余代码,您就可以更改定义属性的方式。 Nullable<T>
为辅助结构提供了一个很好的模型,但仅适用于值类型。一个也适用于引用类型的版本很容易制作,除了没有特殊的编译器和运行时支持(这里不需要):
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;
}
}
根据需要添加方法。
有了这个之后,您可以更改 class 以将您的属性标记为可选:
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);
}
}
然后您可以确定 属性 setter 是否曾被调用,并添加对显式取消设置属性的支持:
public bool IsIdSet() {
return _id.HasValue;
}
public void ResetId() {
_id = default(Optional<int>);
}
我认为检查 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" 看看标题 属性 是否曾经设置过。
我正在使用 C#/.NET 4.5 将 JSON 对象反序列化为本机 .NET 类型。 JSON 看起来像:
{
id: 841,
runningTime: 33.8643736,
title: "Test title"
}
...它反序列化后的 class 看起来像:
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 中的可选键呢?我可以在反序列化后检查它是否为 null,但这并不完美,因为 title
可以在 JSON 本身中合法地设置为 null,我需要知道密钥本身是否已定义。为 title
使用一些占位符值,例如 "UNDEFINED"
也很老套。
所以,如果我使用 JavaScriptDeserializer
来反序列化 JSON,我如何判断一个键是否首先在 JSON 中定义与显式设置为无效?
无需过多更改其余代码,您就可以更改定义属性的方式。 Nullable<T>
为辅助结构提供了一个很好的模型,但仅适用于值类型。一个也适用于引用类型的版本很容易制作,除了没有特殊的编译器和运行时支持(这里不需要):
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;
}
}
根据需要添加方法。
有了这个之后,您可以更改 class 以将您的属性标记为可选:
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);
}
}
然后您可以确定 属性 setter 是否曾被调用,并添加对显式取消设置属性的支持:
public bool IsIdSet() {
return _id.HasValue;
}
public void ResetId() {
_id = default(Optional<int>);
}
我认为检查 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" 看看标题 属性 是否曾经设置过。