我使用的是JSON。NET来序列化连接到REST API的对象。我的对象中需要序列化为JSON的一个属性具有动态属性名。如果此属性的结构中包含的值是数值,则JSON属性为“type_id”,但如果此值为字符串值,则JSON属性名称为“type_code”。我试图为此使用自定义的JsonConverter
,但在尝试序列化时,我收到了一条带有此消息的jsonwritereException
:
"状态属性中的令牌属性名称将导致无效的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(MemberSeriize.OptIn)]
属性
不能设置父对象中属性的名称。当调用转换器的WriteJson
方法时,属性名已经写入JSON;编写器只期望该点的值。这就是为什么你得到一个错误。为了使其工作,必须为父对象创建自定义转换器。然后,该转换器将负责编写其子级的属性名称和值。
后续行动
可以为父对象编写一个转换器,使得应用于它的JSON属性仍然受到尊重,同时仍然实现您想要的结果。我将在下面概述方法。
首先,一点设置。由于您没有说明您的类的名称,因此在本例中,我将假定它被称为Document
。我们只需要对它做一个实质性的更改,那就是从DocTypeIdentifier
属性中删除[JsonConverter]
属性。所以我们有:
[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; }
}
有了这些,我们就可以制造转换器了。方法相当简单:我们将文档
加载到作业对象
,利用它尊重应用的属性这一事实,然后返回并修复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();
}
}
现在我们有了转换器,但问题是我们不能简单地用[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的属性之一具有动态属性名称。如果此属性的struct中包含的值是数字值,则JSON属性为“ type_id”,但是,如果此值是字符串值,则JSON属性名称为“ type_code”。我尝试为此使用自定义,但是在尝试序列化时收到以下消息: “状态为Property的令牌PropertyName
问题内容: 我们如何使JSON属性名称动态化。例如 序列化此对象时,它另存为,但我想使键也像一样动态。任何帮助深表感谢。 问题答案: 您可以使用JsonAnySetter JsonAnyGetter批注。您可以在后面使用实例。万一您总是可以在其他情况下使用或其他实现。下面的示例显示了使用此方法并根据需要创建任意数量的-s是多么容易: 上面的代码打印:
问题内容: 我如何做到这一点: 问题答案: 请改用方括号表示法。 或者,在现代JavaScript中:
问题内容: 我使用不同的数据库,并且根据数据库,我需要将“ id”命名为不同的名称。因此,例如在id中被命名为“ @rid” 对于MongoDB,该ID名为“ _id” 我不知道现代数据库开发人员有什么问题,不仅仅是命名id字段“ id” ^^。但是现在我有一个问题。在某些情况下,如何将ID字段动态序列化/反序列化为“ @rid”,在另一种情况下,如何动态序列化/反序列化为“ _id”? 编辑:
我需要反序列化以下json: 将它的< code>id属性设置为< code>foo_id json属性。 我需要在自定义反序列化程序中执行此操作。实现这一点最简单的方法是什么? 我想以某种方式将json“转换”为 然后将此委托给杰克逊。 在本例中,对象的类型为Foo,但其他对象可能不属于此类。另外,在本例中,json是一个数字,但如果它也是一个字符串,我希望支持。所以,我需要一种通用的方法来做到
问题内容: 我正在一个JSON驱动的项目中,我想为该对象提供一个动态的licensest列表。虽然我可以使用一组键值对来获得权限,但是我想知道是否可以删除属性名,以便 键 是值,而 值 是值。 当我生成JSON时,它输出一个权限数组: 我想知道如何覆盖序列化,以便它使用值而不是属性名称。 问题答案: 您可以使用以下自定义转换器: 用法: JSON示例: 相反,它应该也可以正常工作。 示例: htt