JSON 在 C# 中使用 newtonsoft 进行序列化
JSON serialization using newtonsoft in C#
我有以下模型结构。
public class ReferenceData
{
public string Version { get; set; }
public List<DataItem> Data { get; set; }
}
public class DataItem
{
public Dictionary<string, string> Item { get; set; }
}
在字典中,我添加了键值对并使用 KeyValuePairConverter
设置进行序列化。
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
Converters = new List<JsonConverter>() { new KeyValuePairConverter() }
};
var object = Newtonsoft.Json.JsonConvert.SerializeObject(
referenceData,
Formatting.None,
settings
);
输出是,
{
"data":[
{
"item":{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP",
}
},
{
"item":{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP",
}
},
{
"item":{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP",
}
}
]
}
如果我们不希望item
显示在序列化字符串中,需要在JsonSerializerSettings
中进行什么设置或者有没有其他方法可以做到这一点
请注意,我无法根据需要更改模型结构。
输出应该是:
{
"data":[
{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP"
},
{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP"
},
{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP"
}
]
}
如果你这样改变,结果就会如你所愿;
public class ReferenceData
{
public string Version { get; set; }
public List<Dictionary<string, string>> Data { get; set; }
}
可能的其他解决方案是;
ReferenceData r = new ReferenceData();
r.Data = new List<DataItem>();
r.Data.Add(new DataItem { Item = new Dictionary<string, string>() { { "1", "2" }, { "3", "4" } } });
var anon = new
{
data = r.Data.ToList().Select(x =>
{
dynamic data = new ExpandoObject();
IDictionary<string, object> dictionary = (IDictionary<string, object>)data;
foreach (var key in x.Item.Keys)
dictionary.Add(key, x.Item[key]);
return dictionary;
}
)
};
var result = JsonConvert.SerializeObject(anon);
结果:
{
"data": [
{
"1": "2",
"3": "4"
}
]
}
如果您不能更改 C#,可以使用视图模型并使用适当的结构。它可能比更改 JSON 设置更简单,更容易 return 并且更明确:
public class ReferenceData
{
public string Version { get; set; }
public List<Dictionary<string, string>> Data { get; set; }
}
应该根据需要进行序列化。
如果您使用 Json.NET 5.0 第 5 版或更高版本,则不需要嵌套泛型集合。
您可以使用 JsonExtensionDataAttribute
以便 Item
字典的键和值将被序列化为父对象的一部分。
public class ReferenceData
{
public string version { get; set; }
public List<DataItem> data { get; set; }
}
public class DataItem
{
[JsonExtensionData]
public IDictionary<string, object> item { get; set; }
}
// ...
var referenceData = new ReferenceData {
version = "1.0",
data = new List<DataItem> {
new DataItem {
item = new Dictionary<string, object> {
{"1", "2"},
{"3", "4"}
}
},
new DataItem {
item = new Dictionary<string, object> {
{"5", "8"},
{"6", "7"}
}
}
}
};
Console.WriteLine(JsonConvert.SerializeObject(referenceData));
请注意,您需要 Dictionary<string, object>
而不是 Dictionary<string, string>
。
这是我得到的结果:
{
"version": "1.0",
"data": [
{
"1": "2",
"3": "4"
},
{
"5": "8",
"6": "7"
}
]
}
显然,您可以删除 Version
属性 以获得预期的结果。
您可以按如下方式实现自定义行为:
class Program {
static void Main(string[] args) {
var referenceData = new ReferenceData() {
Data = new List<DataItem>() {
new DataItem(){
Item = new Dictionary<string,string>() {
{"ShortDescription", "Lorem ipssumm"},
{"Title", "some text"},
{"PlanType", "ZEROP"},
}
},
new DataItem(){
Item = new Dictionary<string,string>() {
{"ShortDescription", "Lorem ipssumm"},
{"Title", "some text"},
{"PlanType", "ZEROP"},
}
},
new DataItem(){
Item = new Dictionary<string,string>() {
{"ShortDescription", "Lorem ipssumm"},
{"Title", "some text"},
{"PlanType", "ZEROP"},
}
}
}
};
var settings = new JsonSerializerSettings {
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
Converters = new List<JsonConverter>() { new KeyValuePairConverter(), new CustomJsonSerializableConverter() }
};
File.WriteAllText("hello.json", Newtonsoft.Json.JsonConvert.SerializeObject(
referenceData,
Formatting.Indented,
settings
));
}
}
public class ReferenceData {
public string Version { get; set; }
public List<DataItem> Data { get; set; }
}
[CustomJsonSerializable]
public class DataItem {
public Dictionary<string, string> Item { get; set; }
public static void WriteJson(JsonWriter writer, DataItem value, JsonSerializer serializer) {
serializer.Serialize(writer, value.Item);
}
public static DataItem ReadJson(JsonReader reader, DataItem existingValue, JsonSerializer serializer) {
DataItem result = new DataItem();
result.Item = serializer.Deserialize<Dictionary<string, string>>(reader);
return result;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class CustomJsonSerializableAttribute : Attribute {
public readonly string Read;
public readonly string Write;
public CustomJsonSerializableAttribute()
: this(null, null) {
}
public CustomJsonSerializableAttribute(string read, string write) {
this.Read = read;
this.Write = write;
}
}
public class CustomJsonSerializableConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return objectType.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false) != null;
}
public override bool CanWrite {
get {
return true;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
if(value != null) {
var t = value.GetType();
var attr = (CustomJsonSerializableAttribute)t.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false);
var @delegate = t.GetMethod(attr.Write ?? "WriteJson", new Type[] { typeof(JsonWriter), t, typeof(JsonSerializer) });
@delegate.Invoke(null, new object[] { writer, value, serializer });
} else {
serializer.Serialize(writer, null);
}
}
public override bool CanRead {
get {
return true;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var t = existingValue.GetType();
var attr = (CustomJsonSerializableAttribute)t.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false);
var @delegate = t.GetMethod(attr.Read ?? "ReadJson", new Type[] { typeof(JsonReader), t, typeof(JsonSerializer) });
return @delegate.Invoke(null, new object[] { reader, existingValue, serializer });
}
}
我有以下模型结构。
public class ReferenceData
{
public string Version { get; set; }
public List<DataItem> Data { get; set; }
}
public class DataItem
{
public Dictionary<string, string> Item { get; set; }
}
在字典中,我添加了键值对并使用 KeyValuePairConverter
设置进行序列化。
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
Converters = new List<JsonConverter>() { new KeyValuePairConverter() }
};
var object = Newtonsoft.Json.JsonConvert.SerializeObject(
referenceData,
Formatting.None,
settings
);
输出是,
{
"data":[
{
"item":{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP",
}
},
{
"item":{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP",
}
},
{
"item":{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP",
}
}
]
}
如果我们不希望item
显示在序列化字符串中,需要在JsonSerializerSettings
中进行什么设置或者有没有其他方法可以做到这一点
请注意,我无法根据需要更改模型结构。
输出应该是:
{
"data":[
{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP"
},
{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP"
},
{
"ShortDescription":"Lorem ipssumm",
"Title":"some text",
"PlanType":"ZEROP"
}
]
}
如果你这样改变,结果就会如你所愿;
public class ReferenceData
{
public string Version { get; set; }
public List<Dictionary<string, string>> Data { get; set; }
}
可能的其他解决方案是;
ReferenceData r = new ReferenceData();
r.Data = new List<DataItem>();
r.Data.Add(new DataItem { Item = new Dictionary<string, string>() { { "1", "2" }, { "3", "4" } } });
var anon = new
{
data = r.Data.ToList().Select(x =>
{
dynamic data = new ExpandoObject();
IDictionary<string, object> dictionary = (IDictionary<string, object>)data;
foreach (var key in x.Item.Keys)
dictionary.Add(key, x.Item[key]);
return dictionary;
}
)
};
var result = JsonConvert.SerializeObject(anon);
结果:
{
"data": [
{
"1": "2",
"3": "4"
}
]
}
如果您不能更改 C#,可以使用视图模型并使用适当的结构。它可能比更改 JSON 设置更简单,更容易 return 并且更明确:
public class ReferenceData
{
public string Version { get; set; }
public List<Dictionary<string, string>> Data { get; set; }
}
应该根据需要进行序列化。
如果您使用 Json.NET 5.0 第 5 版或更高版本,则不需要嵌套泛型集合。
您可以使用 JsonExtensionDataAttribute
以便 Item
字典的键和值将被序列化为父对象的一部分。
public class ReferenceData
{
public string version { get; set; }
public List<DataItem> data { get; set; }
}
public class DataItem
{
[JsonExtensionData]
public IDictionary<string, object> item { get; set; }
}
// ...
var referenceData = new ReferenceData {
version = "1.0",
data = new List<DataItem> {
new DataItem {
item = new Dictionary<string, object> {
{"1", "2"},
{"3", "4"}
}
},
new DataItem {
item = new Dictionary<string, object> {
{"5", "8"},
{"6", "7"}
}
}
}
};
Console.WriteLine(JsonConvert.SerializeObject(referenceData));
请注意,您需要 Dictionary<string, object>
而不是 Dictionary<string, string>
。
这是我得到的结果:
{
"version": "1.0",
"data": [
{
"1": "2",
"3": "4"
},
{
"5": "8",
"6": "7"
}
]
}
显然,您可以删除 Version
属性 以获得预期的结果。
您可以按如下方式实现自定义行为:
class Program {
static void Main(string[] args) {
var referenceData = new ReferenceData() {
Data = new List<DataItem>() {
new DataItem(){
Item = new Dictionary<string,string>() {
{"ShortDescription", "Lorem ipssumm"},
{"Title", "some text"},
{"PlanType", "ZEROP"},
}
},
new DataItem(){
Item = new Dictionary<string,string>() {
{"ShortDescription", "Lorem ipssumm"},
{"Title", "some text"},
{"PlanType", "ZEROP"},
}
},
new DataItem(){
Item = new Dictionary<string,string>() {
{"ShortDescription", "Lorem ipssumm"},
{"Title", "some text"},
{"PlanType", "ZEROP"},
}
}
}
};
var settings = new JsonSerializerSettings {
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
Converters = new List<JsonConverter>() { new KeyValuePairConverter(), new CustomJsonSerializableConverter() }
};
File.WriteAllText("hello.json", Newtonsoft.Json.JsonConvert.SerializeObject(
referenceData,
Formatting.Indented,
settings
));
}
}
public class ReferenceData {
public string Version { get; set; }
public List<DataItem> Data { get; set; }
}
[CustomJsonSerializable]
public class DataItem {
public Dictionary<string, string> Item { get; set; }
public static void WriteJson(JsonWriter writer, DataItem value, JsonSerializer serializer) {
serializer.Serialize(writer, value.Item);
}
public static DataItem ReadJson(JsonReader reader, DataItem existingValue, JsonSerializer serializer) {
DataItem result = new DataItem();
result.Item = serializer.Deserialize<Dictionary<string, string>>(reader);
return result;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class CustomJsonSerializableAttribute : Attribute {
public readonly string Read;
public readonly string Write;
public CustomJsonSerializableAttribute()
: this(null, null) {
}
public CustomJsonSerializableAttribute(string read, string write) {
this.Read = read;
this.Write = write;
}
}
public class CustomJsonSerializableConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return objectType.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false) != null;
}
public override bool CanWrite {
get {
return true;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
if(value != null) {
var t = value.GetType();
var attr = (CustomJsonSerializableAttribute)t.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false);
var @delegate = t.GetMethod(attr.Write ?? "WriteJson", new Type[] { typeof(JsonWriter), t, typeof(JsonSerializer) });
@delegate.Invoke(null, new object[] { writer, value, serializer });
} else {
serializer.Serialize(writer, null);
}
}
public override bool CanRead {
get {
return true;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var t = existingValue.GetType();
var attr = (CustomJsonSerializableAttribute)t.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false);
var @delegate = t.GetMethod(attr.Read ?? "ReadJson", new Type[] { typeof(JsonReader), t, typeof(JsonSerializer) });
return @delegate.Invoke(null, new object[] { reader, existingValue, serializer });
}
}