反序列化时是否可以将字段保留为原始文本?
Is it possible to leave fields as raw text when deserializing?
我有json这样的
{
"guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
"status": "complete",
"type": "colors",
"results": {
"events": [
{
"title": "event1",
"other": {
"Red": "red",
"Green": "green",
"Blue": "blue"
}
},
{
"title": "event2",
"other": {
"Yelow": "yellow",
"Orange": "orange"
}
}
]
}
}
和类反序列化看起来像这样
public class Other
{
public string Red { get; set; }
public string Green { get; set; }
public string Blue { get; set; }
public string Yelow { get; set; }
public string Orange { get; set; }
}
public class Event
{
public string title { get; set; }
public Other other { get; set; }
}
public class Results
{
public List<Event> events { get; set; }
}
public class Root
{
public string guid { get; set; }
public string status { get; set; }
public string type { get; set; }
public Results results { get; set; }
}
当我用
反序列化这个json时
var root = JsonConvert.DeserializeObject<Root>(JsonContent);
一切正常。
问题是json段"Other"
的内容是可变的,我不知道它的完整内容。
我还需要把这个 类 放入数据库中。
有没有办法将 json 部分 "Other"
反序列化为一个带有原始文本的字符串字段,并且看起来像这样:
public class Other
{
public string AllFieldsFromOtherSectionAsRawText { get; set; }
}
Other 不是字典表示吗?
你不能把它写成字典吗
public Dictionary<String,String> other { get; set; }
示例:
[Newtonsoft.Json.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, string> other
根据文档,您 DeserializeObject 类型为 Dictionary:
JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
https://www.newtonsoft.com/json/help/html/DeserializeDictionary.htm
如果您这样定义 Other
class:
public class Other
{
public Other(string rawData)
{
Content = rawData;
}
public string Content { get; }
}
然后您可以编写一个自定义 JsonConverter
,它将把您的 other
节点视为 string
:
class ObjectToStringJsonConverter : JsonConverter
{
private readonly Type theType;
public ObjectToStringJsonConverter(Type type) => theType = type;
public override bool CanConvert(Type objectType) => objectType == theType;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
=> throw new NotImplementedException();
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
return Activator.CreateInstance(theType, args: token.ToString());
}
throw new NotSupportedException("The related node is not object");
}
}
这里唯一的技巧是这一行:
Activator.CreateInstance(theType, args: token.ToString());
- 这里我们创建一个新的
Other
实例,并将 other
节点的字符串表示形式传递给构造函数。
那么用法将是这样的:
var root = JsonConvert.DeserializeObject<Root>(json, new[] { new ObjectToStringJsonConverter(typeof(Other)) });
从代码中删除 class Other,并修复事件 class
public class Event
{
public string title { get; set; }
[JsonProperty(PropertyName = "other")]
public Dictionary<string, string> otherDict { get; set; }
[Newtonsoft.Json.JsonIgnore]
public IEnumerable<string> Other
{
get { return otherDict.Values.ToArray(); }
}
[Newtonsoft.Json.JsonIgnore]
public string AllFieldsFromOtherSectionAsRawText
{
get { return string.Join(",", Other); }
}
}
输出
{
"guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
"status": "complete",
"type": "colors",
"results": {
"events": [
{
"title": "event1",
"other": {
"Red": "red",
"Green": "green",
"Blue": "blue"
},
"AllFieldsFromOtherSectionAsRawText": "red,green,blue"
},
{
"title": "event2",
"other": {
"Yelow": "yellow",
"Orange": "orange"
},
"AllFieldsFromOtherSectionAsRawText": "yellow,orange"
}
]
}
}
我有json这样的
{
"guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
"status": "complete",
"type": "colors",
"results": {
"events": [
{
"title": "event1",
"other": {
"Red": "red",
"Green": "green",
"Blue": "blue"
}
},
{
"title": "event2",
"other": {
"Yelow": "yellow",
"Orange": "orange"
}
}
]
}
}
和类反序列化看起来像这样
public class Other
{
public string Red { get; set; }
public string Green { get; set; }
public string Blue { get; set; }
public string Yelow { get; set; }
public string Orange { get; set; }
}
public class Event
{
public string title { get; set; }
public Other other { get; set; }
}
public class Results
{
public List<Event> events { get; set; }
}
public class Root
{
public string guid { get; set; }
public string status { get; set; }
public string type { get; set; }
public Results results { get; set; }
}
当我用
反序列化这个json时var root = JsonConvert.DeserializeObject<Root>(JsonContent);
一切正常。
问题是json段"Other"
的内容是可变的,我不知道它的完整内容。
我还需要把这个 类 放入数据库中。
有没有办法将 json 部分 "Other"
反序列化为一个带有原始文本的字符串字段,并且看起来像这样:
public class Other
{
public string AllFieldsFromOtherSectionAsRawText { get; set; }
}
Other 不是字典表示吗?
你不能把它写成字典吗
public Dictionary<String,String> other { get; set; }
示例:
[Newtonsoft.Json.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, string> other
根据文档,您 DeserializeObject 类型为 Dictionary:
JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
https://www.newtonsoft.com/json/help/html/DeserializeDictionary.htm
如果您这样定义 Other
class:
public class Other
{
public Other(string rawData)
{
Content = rawData;
}
public string Content { get; }
}
然后您可以编写一个自定义 JsonConverter
,它将把您的 other
节点视为 string
:
class ObjectToStringJsonConverter : JsonConverter
{
private readonly Type theType;
public ObjectToStringJsonConverter(Type type) => theType = type;
public override bool CanConvert(Type objectType) => objectType == theType;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
=> throw new NotImplementedException();
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
return Activator.CreateInstance(theType, args: token.ToString());
}
throw new NotSupportedException("The related node is not object");
}
}
这里唯一的技巧是这一行:
Activator.CreateInstance(theType, args: token.ToString());
- 这里我们创建一个新的
Other
实例,并将other
节点的字符串表示形式传递给构造函数。
那么用法将是这样的:
var root = JsonConvert.DeserializeObject<Root>(json, new[] { new ObjectToStringJsonConverter(typeof(Other)) });
从代码中删除 class Other,并修复事件 class
public class Event
{
public string title { get; set; }
[JsonProperty(PropertyName = "other")]
public Dictionary<string, string> otherDict { get; set; }
[Newtonsoft.Json.JsonIgnore]
public IEnumerable<string> Other
{
get { return otherDict.Values.ToArray(); }
}
[Newtonsoft.Json.JsonIgnore]
public string AllFieldsFromOtherSectionAsRawText
{
get { return string.Join(",", Other); }
}
}
输出
{
"guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
"status": "complete",
"type": "colors",
"results": {
"events": [
{
"title": "event1",
"other": {
"Red": "red",
"Green": "green",
"Blue": "blue"
},
"AllFieldsFromOtherSectionAsRawText": "red,green,blue"
},
{
"title": "event2",
"other": {
"Yelow": "yellow",
"Orange": "orange"
},
"AllFieldsFromOtherSectionAsRawText": "yellow,orange"
}
]
}
}