我正在使用JSON.NET对对象进行序列化以连接到REST
API。我对象中需要序列化为JSON的属性之一具有动态属性名称。如果此属性的struct中包含的值是数字值,则JSON属性为“
type_id”,但是,如果此值是字符串值,则JSON属性名称为“
type_code”。我尝试为此使用自定义JsonConverter
,但是JsonWriterException
在尝试序列化时收到以下消息:
“状态为Property的令牌PropertyName将导致无效的JSON对象。路径”。
下面是对象的子集,如下所示,我没有在对象中为此指定属性名称:
[JsonProperty("title",Required=Required.Always,Order=1)]
public string Title { get; set; }
[JsonProperty("date",Order=3)]
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime Date { get; set; }
[JsonProperty(Order=2)]
[JsonConverter(typeof(TypeIdentifierJsonConverter))]
public TypeIdentifier DocTypeIdentifier { get; set; }
在TypeIdentifier类中,我的WriteJson()方法具有以下内容:
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
TypeIdentifier docTypeId;
id= (TypeIdentifier) value;
writer.WritePropertyName(id.ParameterName);
writer.WriteValue(id.Value);
}
但是,我假设它默认使用对象属性的名称,而不是我的自定义名称,从而导致JSON字符串中的单个值具有两个属性名称。由于未明确指定JsonPropertyAttribute标记似乎会拉动对象的属性名称,因此如何动态设置属性名称呢?
注意:此对象将永远不需要从此应用程序反序列化。
编辑: 此对象标记有[JsonObject(MemberSerialization.OptIn)]
属性
一个JsonConverter
不能设置在一个父对象的属性的名称。WriteJson
调用转换器的方法时,属性名称已被写入JSON;作者只期望有一个价值。这就是为什么您会得到一个错误。为了使这项工作,必须为父对象创建自定义转换器。然后,该转换器将负责编写其子代的属性名称和值。
跟进
可以为父对象编写一个转换器,以便仍尊重应用到它的JSON属性,同时仍然获得所需的结果。我将在下面概述该方法。
首先,进行一些设置。由于您没有说出您的班级叫什么,因此在此示例中,我假设它被称为Document
。我们只需要对其进行实质性更改,那就是[JsonConverter]
从DocTypeIdentifier
属性中删除该属性。因此,我们有:
[JsonObject(MemberSerialization.OptIn)]
class Document
{
[JsonProperty("title", Required = Required.Always, Order = 1)]
public string Title { get; set; }
[JsonProperty("date", Order = 3)]
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime Date { get; set; }
[JsonProperty(Order = 2)]
public TypeIdentifier DocTypeIdentifier { get; set; }
public string OtherStuff { get; set; }
}
您也没有显示TypeIdentifier
该类的代码,因此,出于示例的考虑,我假设它看起来像这样:
class TypeIdentifier
{
public string Value { get; set; }
public string ParameterName { get; set; }
}
有了这些,我们就可以制造转换器。该方法非常简单:我们利用尊重应用的属性这一事实将其加载Document
到中JObject
,然后返回并修复的序列化,DocTypeIdentifier
因为它需要特殊处理。一旦我们有了这一点,我们写出来JObject
的JsonWriter
。这是代码:
class DocumentConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Document));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Document doc = (Document)value;
// Create a JObject from the document, respecting existing JSON attribs
JObject jo = JObject.FromObject(value);
// At this point the DocTypeIdentifier is not serialized correctly.
// Fix it by replacing the property with the correct name and value.
JProperty prop = jo.Children<JProperty>()
.Where(p => p.Name == "DocTypeIdentifier")
.First();
prop.AddAfterSelf(new JProperty(doc.DocTypeIdentifier.ParameterName,
doc.DocTypeIdentifier.Value));
prop.Remove();
// Write out the JSON
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
现在我们有了转换器,但是要注意的是,我们不能简单地Document
使用[JsonConverter]
属性装饰类以使用它。如果这样做的话,最终会导致递归循环,因为在将文档加载到中时,转换器会尝试使用自身JObject
。因此,我们需要创建转换器的实例,然后通过设置将其传递给串行器。转换器的CanConvert
方法可确保将其用于正确的类。该JObject.FromObject
方法在内部使用其他序列化器实例,因此不会看到DocumentConverter
,因此不会遇到麻烦。
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new DocumentConverter());
string json = JsonConvert.SerializeObject(doc, settings);
这是演示如何运行转换器的演示:
class Program
{
static void Main(string[] args)
{
Document doc = new Document
{
Title = "How to write a JSON converter",
Date = DateTime.Today,
DocTypeIdentifier = new TypeIdentifier
{
ParameterName = "type_id",
Value = "26"
},
OtherStuff = "this should not appear in the JSON"
};
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new DocumentConverter());
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(doc, settings);
Console.WriteLine(json);
}
}
这是上面的输出:
{
"title": "How to write a JSON converter",
"type_id": "26",
"date": "2014-03-28T00:00:00-05:00"
}
我使用的是JSON。NET来序列化连接到REST API的对象。我的对象中需要序列化为JSON的一个属性具有动态属性名。如果此属性的结构中包含的值是数值,则JSON属性为“type_id”,但如果此值为字符串值,则JSON属性名称为“type_code”。我试图为此使用自定义的,但在尝试序列化时,我收到了一条带有此消息的: "状态属性中的令牌属性名称将导致无效的JSON对象。路径"。" 下面是我的
问题内容: 我正在尝试将一些JSON数据反序列化为应用程序的对象。到现在为止还不错,因为JSON数据上的属性是静态的(带有值的键)。现在,我得到了一个结果,其中的关键是动态数据。 这是一个示例JSON网址: http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info 由此产生的JSON是: 好的
问题内容: 我正在尝试对a进行序列化/反序列化,如果对象是简单类型,这似乎很好,但是当对象更复杂时,它不起作用。 我有这个课: 在我的字典中,我添加了一个带有“重定向链”键的键和一些带有“状态”,“网址”,“父网址”键的简单字符串。我从JSON.Net返回的字符串如下所示: 我用来序列化的代码如下: 反序列化我正在做的事情: 字典恢复正常,所有字符串恢复正常,但是列表未正确反序列化。它只是作为 当
问题内容: 我如何做到这一点: 问题答案: 请改用方括号表示法。 或者,在现代JavaScript中:
问题内容: 我使用不同的数据库,并且根据数据库,我需要将“ id”命名为不同的名称。因此,例如在id中被命名为“ @rid” 对于MongoDB,该ID名为“ _id” 我不知道现代数据库开发人员有什么问题,不仅仅是命名id字段“ id” ^^。但是现在我有一个问题。在某些情况下,如何将ID字段动态序列化/反序列化为“ @rid”,在另一种情况下,如何动态序列化/反序列化为“ _id”? 编辑:
问题内容: 我如何才能序列化一个特定的属性,但又防止其反序列化回POCO?是否可以使用属性装饰特定属性? 基本上,我正在寻找一个与ShouldSerialize *方法等效的反序列化方法。 我知道我可以编写一个自定义转换器,但是这样做似乎有点过头了。 编辑: 这里还有一些背景。这背后的原因是我的课看起来像: 我需要请求的属性,但是我不希望它反序列化并触发设置程序逻辑。 问题答案: 最简单的方法是将