【发布时间】:2015-06-03 03:12:13
【问题描述】:
我想要一个与 JSON 几乎相同的序列化格式,只是键值表示为 <key>="<value>" 而不是 "<key>":"<value>"。
使用 Newtonsoft,我制作了一个名为 TsonConverter 的自定义 JsonConverter,它工作得相当好,只是它不能“看到”嵌入式字典。给定以下类型:
public class TraceyData
{
[Safe]
public string Application { get; set; }
[Safe]
public string SessionID { get; set; }
[Safe]
public string TraceID { get; set; }
[Safe]
public string Workflow { get; set; }
[Safe]
public Dictionary<string, string> Tags {get; set; }
[Safe]
public string[] Stuff {get; set;}
}
还有如下代码:
TsonConverter weird = new TsonConverter();
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
settings.Converters.Add(weird);
var tracey = new TraceyData();
tracey.TraceID = Guid.NewGuid().ToString();
tracey.SessionID = "5";
tracey.Tags["Referrer"] = "http://www.sky.net/deals";
tracey.Stuff = new string[] { "Alpha", "Bravo", "Charlie" };
tracey.Application = "Responsive";
string stuff = JsonConvert.SerializeObject(tracey, settings);
我明白了:
[Application="Responsive" SessionID="5" TraceID="082ef853-92f8-4ce8-9f32-8e4f792fb022" Tags={"Referrer":"http://www.sky.net/deals"} Stuff=["Alpha","Bravo" "查理"]]
显然,我还覆盖了 StartObject/EndObject 表示法,将 { } 替换为 [ ]。否则结果还不错。
但是,内部字典仍然存在问题。为了
要将字典也转换为使用我的<key>="<value>" 格式,看来我必须创建一个deep dictionary converter。
我想知道是否有更简单的方法可以做到这一点。
也许 Newtonsoft 工具有一个“属性生成器”和“键值”生成器属性,我可以设置它们来为我全局处理这个问题?
有什么建议吗?
当我们在这里时,我想知道是否有我可以设置的 StartObject/EndObject 格式化程序属性覆盖,它可以处理我上面显示的其他自定义。为这些简单的更改“跳过”制作 JsonConverter 工具会很好。
顺便说一句:
- 我的自定义 JsonConverter 正在根据示例中显示的
[Safe]属性选择要序列化的属性。这是另一个不错的选择。如果 JSon 设置可以公开一个“属性处理程序”属性,让我覆盖通常的 JSon 属性以支持我自己的属性,那就太好了。 - 我不需要反序列化这种格式。它旨在作为一种单向操作。如果有人还想解释如何反序列化我的自定义格式,这是一个有趣的奖励,但绝对没有必要回答这个问题。
附录
下面是我制作的 TraceConverter。它引用了一个简单地保存属性信息的FieldMetaData 类。
public class TsonConverter : JsonConverter
{
public override bool CanRead
{
get
{
return false;
}
}
public override bool CanConvert(Type ObjectType)
{
return DataClassifier.TestForUserType(ObjectType);
}
public override void WriteJson(
JsonWriter writer, object value, JsonSerializer serializer)
{
Type objType = value.GetType();
var props = objType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var propMap = from p in props
from a in p.GetCustomAttributes(typeof(ProfileAttribute), false)
select new FieldMetaData(p, (ProfileAttribute)a);
//writer.WriteStartObject();
writer.WriteStartArray();
bool loopStarted = true;
foreach(var prop in propMap){
object rawValue = prop.GetValue(value);
if (rawValue != null || serializer.NullValueHandling == NullValueHandling.Include)
{
string jsonValue = JsonConvert.SerializeObject(prop.GetValue(value), this);
if (loopStarted)
{
loopStarted = false;
writer.WriteRaw(String.Format("{0}={1}", prop.Name, jsonValue));
}
else
{
writer.WriteRaw(String.Format(" {0}={1}", prop.Name, jsonValue));
}
}
//writer.WriteRaw(String.Format("{0}={1}", prop.Name, prop.GetValue(value)));
//writer.WritePropertyName(prop.Name, false);
//writer.WriteValue(prop.GetValue(value));
}
writer.WriteEndArray();
}
public override object ReadJson(
JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
【问题讨论】:
-
发布您的 jsonconverter 类并寻找其他实现 blog.maskalik.com/asp-net/…
-
示例输出中的属性之间没有逗号分隔符,但是在您的初始段落中,您没有指定应删除逗号。它应该存在吗?