我很难重写自定义 JsonConverter 的 WriteJson 方法,以便稍微改变序列化的执行方式。
我需要调用一个 REST 服务,该服务接受具有通用部分的特定输入。我可以使用以下有效负载格式重现我遇到的问题:
public sealed class JsonField
{
public string Key { get; set; }
public object Value { get; set; }
public string OtherParam { get; set; }
}
public sealed class JsonPayload
{
public string Item1 { get; set; }
public string Item2 { get; set; }
public List<JsonField> Fields { get; set; }
}
我调用的 REST API 需要让 Fields 成为一个对象,其中包含尽可能多的字段,其名称与原始集合中指定的 Key 属性相对应。就像这样:
{
"Item1" : "Value1",
"Item2" : "Value2",
...
"Fields":
{
"Key1": {"Value":"Value1", "OtherParam":"other1"}
"Key2": {"Value":42, "OtherParam":"other2"}
}
}
但是,使用默认选项,有效负载会像这样序列化:
{
"Item1" : "Value1",
"Item2" : "Value2",
...
"Fields":[
{ "Key":"Key1", "Value":"Value1", "OtherParam":"other1" }
{ "Key":"Key2", "Value":42, "OtherParam":"other2" }
]
}
您注意到有一个对象集合,而我想要一个对象。
另外,我希望键名称是字段中各个属性的名称。
我很难弄清楚如何在自定义转换器中使用 JToken、JProperty、JValue 对象。事实上,我从未尝试过这样的事情,所以我发现很难理解这些概念。
我尝试创建两个自定义转换器,一个在类的范围内,以防止生成集合,第二个在集合的范围内,但到目前为止没有成功。
这是我尝试过的:
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var token = JToken.FromObject(value);
var key = token["Key"];
if (key == null)
throw new Exception("missing key");
var propertyName = key.ToString();
var json = new StringBuilder();
json.Append("{");
foreach (var child in token.Children())
{
var property = child as JProperty;
if (property == null || property.Name == "Key")
continue;
var propName = property.Name;
var propValue = JsonConvert.SerializeObject(property.Value);
json.AppendFormat("\"{0}\": {1},", propName, propValue);
}
if (json.Length > 1)
json.Remove(json.Length - 1, 1);
json.Append("}");
var newToken = JToken.Parse(json.ToString());
var serializedObject = JsonConvert.SerializeObject(newToken);
writer.WriteStartObject();
writer.WritePropertyName(propertyName);
writer.WriteToken(newToken.CreateReader());
writer.WriteEndObject();
}
有没有办法实现我想要实现的目标?
也许我以错误的方式处理这个问题,所以请,如果您有更简单的选择,那么请务必毫不犹豫地分享您的想法。