我产生以下输出:
[
{
"info": {
"type": 6,
"message": "a message"
}
},
{
"detail": {
"type": 8,
"something": "a different thing"
}
}
]
我现在正在这样做:
Dictionary<string, object> Result = new Dictionary<string, object>();
Result.Add("info", new Info() { Type = 6, message = "a message"});
Result.Add("detail", new Detail() { Type = 8, something = "a different thing" });
JsonConvert.SerializeObject(new object[] { _Errors });
但是当涉及到这样的输出时,这不起作用:
[
{
"info": {
"type": 6,
"message": "a message"
}
},
{
"info": {
"type": 6,
"message": "another message"
}
}
]
由于这需要字典中的重复键,我不知道哪个结构将产生这个输出。
KeyValuePair不会工作,因为这导致“key”:“info”......等等。 此外,由于元素数量是动态的,因此具有多个使用相同JsonProperty属性的成员的类将无法工作。
答案 0 :(得分:1)
我假设你想要的是这个输出:
[
{
"Info": {
"Type": 5,
"Message": "A message 1"
}
},
{
"Info": {
"Type": 6,
"Message": "A message 3"
}
},
{
"Info": {
"Type": 7,
"Message": "A message 2"
}
},
{
"Error": {
"Type": 8,
"Something": "A different thing"
}
}
]
实现自己的JsonConvert,这是一个提供上述序列化
的示例using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
namespace JsonSerialization
{
public class ResultsEntrySerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var entry = value as IResultsEntry;
if (entry == null) throw new ArgumentException("Cannot convert parameter", nameof(value));
writer.WriteStartObject();
writer.WritePropertyName(entry.Name);
serializer.Serialize(writer, entry.Entry);
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
//TODO: I leave this up to the reader
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType.GetInterfaces().Contains(typeof(IResultsEntry));
}
}
[JsonConverter(typeof(ResultsEntrySerializer))]
interface IResultsEntry
{
string Name { get; }
object Entry { get; set; }
}
class Info
{
public int Type { get; set; }
public string Message { get; set; }
}
class InfoEntry : IResultsEntry
{
string IResultsEntry.Name => "Info";
object IResultsEntry.Entry
{
get => Entry;
set => Entry = (Info)value;
}
public Info Entry { get; set; }
}
class Detail
{
public int Type { get; set; }
public string Something { get; set; }
}
class DetailEntry : IResultsEntry
{
string IResultsEntry.Name => "Error";
object IResultsEntry.Entry
{
get => Entry;
set => Entry = (Detail)value;
}
public Detail Entry { get; set; }
}
class Program
{
static void Main(string[] args)
{
var list = new List<IResultsEntry>
{
new InfoEntry
{
Entry = new Info { Type = 5, Message = "A message 1" }
},
new InfoEntry
{
Entry = new Info { Type = 6, Message = "A message 3" }
},
new InfoEntry
{
Entry = new Info { Type = 7, Message = "A message 2" }
},
new DetailEntry
{
Entry = new Detail { Type = 8, Something = "A different thing" }
}
};
Console.WriteLine(JsonConvert.SerializeObject(list));
Console.ReadLine();
}
}
}
此外,如果你想要它们的小写也是微不足道的,请看这个Stackoverflow帖子:Json keys lowercase
答案 1 :(得分:0)
public class DupKey {
public string Name { get; set; }
public int Index { get; set; }
public override string ToString() {
return Name;
}
public override bool Equals(object obj) {
if(!(obj is DupKey)) return false;
return Index == ((DupKey)obj).Index;
}
public override int GetHashCode() {
return Index.GetHashCode();
}
}
但最后我发现这会产生错误的结果。 最后,我发现了一个解决方案(不需要自己的序列化器),它可以提供正确的结果。
因为这对我来说看起来很普遍,所以我在这里发布。
public class DynamicJsonEntry : DynamicObject {
private string _JsonName;
public object Element { get; set; }
public DynamicJsonEntry(string pJsonName, object pElement) : this(pJsonName) {
Element = pElement;
}
public DynamicJsonEntry(string pJsonName) {
if(string.IsNullOrWhiteSpace(pJsonName)) {
throw new ArgumentNullException(nameof(pJsonName));
}
_JsonName = pJsonName;
}
public override IEnumerable<string> GetDynamicMemberNames() {
yield return _JsonName;
foreach(var prop in GetType().GetProperties().Where(a => a.CanRead && a.GetIndexParameters().Length == 0 && a.Name != nameof(Element))) {
yield return prop.Name;
}
}
public override bool TryGetMember(GetMemberBinder pBinder, out object pResult) {
if(pBinder.Name == _JsonName) {
pResult = Element;
return true;
}
return base.TryGetMember(pBinder, out pResult);
}
}
现在我可以像这样添加任何名称我想要的条目:
List<DynamicJsonEntry> lRet = new List<DynamicJsonEntry>();
lRet.Add(new DynamicJsonEntry("info", new Info() { Type = 6, message = "a message" }));
lRet.Add(new DynamicJsonEntry("detail", new Detail() { Type = 8, something = "a different thing" }));
lRet.Add(new DynamicJsonEntry("info", new Info() { Type = 6, message = "a second message" }));
感谢Joachim的帮助。