在反序列化时,备用属性名称

13 浏览
0 Comments

在反序列化时,备用属性名称

参考这个问题:

如何在使用Json.net进行序列化时更改属性名称?

当然,很好,但我能同时拥有蛋糕和吃掉它吗?

我想要的是一种让属性具有替代名称的方式,以便字符串可以包含其中之一。

类似于:

[BetterJsonProperty(PropertyName = "foo_bar")]
public string FooBar { get; set; }

这样做,无论是

{

"FooBar": "yup"

}

还是

{

"foo_bar":"uhuh"

}

都会按预期反序列化。

可以没有属性的解决方案,或者在类上使用一个属性,如:

 [AllowCStylePropertyNameAlternatives]

0
0 Comments

在使用Json.NET进行反序列化时,有时候会遇到"Alternate property name while deserializing"的问题。这个问题的出现是因为在反序列化过程中,属性名与JSON数据中的键不匹配。

为了解决这个问题,我们可以通过拦截序列化/反序列化过程来提前进行处理。一种方法是通过重写JsonReader和JsonWriter来实现。

首先,我们创建一个CustomJsonWriter类,继承自JsonTextWriter,并重写WritePropertyName方法。在这个方法中,我们可以通过一个字典来映射属性名,将原本的属性名替换为我们想要的属性名。

接下来,我们创建一个CustomJsonReader类,继承自JsonTextReader,并重写Value属性。在这个属性中,我们可以判断当前的Token类型,如果是属性名,则通过字典将其替换为我们想要的属性名。

实现了上述两个类后,我们可以通过创建CustomJsonWriter和CustomJsonReader的实例,将其传入JsonSerializer的Serialize和Deserialize方法中,来进行序列化和反序列化操作。

例如,对于序列化操作,我们可以这样使用:

var mappings = new Dictionary
{
    {"Property1", "Equivalent1"},
    {"Property2", "Equivalent2"},
};
var builder = new StringBuilder();
JsonSerializer.Create().Serialize(new CustomJsonWriter(new StringWriter(builder), mappings), your_object);

而对于反序列化操作,我们可以这样使用:

var mappings = new Dictionary
{
    {"Equivalent1", "Property1"},
    {"Equivalent2", "Property2"},
};
var txtReader = new CustomJsonReader(new StringReader(jsonString), mappings);
var your_object = JsonSerializer.Create().Deserialize(txtReader);

然而,有时候上述方法可能会出现问题,导致WritePropertyName方法没有被调用,或者CustomJsonReader的Value方法出现"given key was not present in dictionary"的错误。

如果遇到这种情况,还有另一种解决方案可供参考。具体可以参考stackoverflow.com/questions/15915503/…中的解答。

0
0 Comments

在使用Json.NET进行反序列化时,有时候会遇到属性名在JSON中与对象的属性名不完全匹配的情况。这种情况下,Json.NET会抛出“Alternate property name while deserializing”(在反序列化时使用备用属性名)的异常。

为了解决这个问题,可以创建一个自定义的JsonConverter来实现属性名的灵活匹配。具体的步骤如下:

首先,创建一个继承自JsonConverter的类,例如LaxPropertyNameMatchingConverter。该类需要实现CanConvert、CanWrite、ReadJson和WriteJson这几个方法。

在CanConvert方法中,判断传入的对象类型是否为类(objectType.IsClass),返回一个布尔值。

在CanWrite方法中,返回false,表示不支持写入操作。

在ReadJson方法中,首先创建一个objectType类型的实例,并获取该类型的所有属性。然后使用JObject.Load方法从JsonReader中加载JSON对象,遍历JSON对象的属性。在遍历的过程中,通过正则表达式将非字母数字字符从属性名中移除,然后使用LINQ查询找到匹配的属性,并使用反射设置属性的值。

在WriteJson方法中,抛出一个NotImplementedException异常,表示不支持写入操作。

然后,可以通过在需要使用该自定义转换器的类上添加[JsonConverter(typeof(LaxPropertyNameMatchingConverter))]属性来使用该转换器。例如,在MyClass类上添加该属性。

最后,可以通过调用JsonConvert.DeserializeObject方法将JSON字符串转换为对象,并输出对象的属性值。

除了使用自定义转换器的方法外,还可以通过修改Json.NET的源代码来解决这个问题。具体的做法是在JsonPropertyCollection类的GetClosestMatchProperty方法中添加一行代码,将属性名中的非字母数字字符移除后再进行匹配。这样就可以在不需要特殊转换器或属性的情况下实现属性名的灵活匹配。

然而,修改源代码也有一些问题,可能会引起其他潜在的问题,因此需要谨慎操作。

通过使用自定义转换器或修改源代码,可以解决Json.NET反序列化时属性名不完全匹配的问题。这样就可以实现属性名的灵活匹配,提高代码的灵活性和可维护性。

0