我在我的应用程序中使用NewtonSoft.Json
将许多类型的对象序列化为字符串并将它们发送到第三方服务。现在,其中一些服务对Json格式有限制,例如它们不支持JSON属性名称中的点:
{
"PropertyOne":{
"SubProperty.One":"SubValue.One" <- invalid!
},
"Property.Two":"ValueTwo" <- invalid!
}
如何修改NewtonSoft.Json
序列化对象的方式,以便用例如下划线替换属性名称中的所有点:
{
"PropertyOne":{
"SubProperty_One":"SubValue.One"
},
"Property_Two":"ValueTwo"
}
注意:我无法用DataAnnotations
属性实现这一点,因为我序列化的一些对象在第三方库中,我无法修改它们。
答案 0 :(得分:1)
您可以使用自定义ContractResolver轻松完成此操作:
class ReplaceDotsWithUnderscoresResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty prop = base.CreateProperty(member, memberSerialization);
prop.PropertyName = prop.PropertyName.Replace('.', '_');
return prop;
}
}
像这样使用:
JsonSerializerSettings settings = new JsonSerializerSettings
{
ContractResolver = new ReplaceDotsWithUnderscoresResolver(),
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(your_object, settings);
答案 1 :(得分:0)
您可以使用AutoMapper并将第三方类型映射到您自己的类型。然后,您就可以将JsonPropertyAttribute应用于需要自定义名称的属性。
另一种方法可能是用正则表达式替换生成的JSON:
var json = @"{
""PropertyOne"":{
""SubProperty.One"":""SubValue.One""
},
""Property.Two.Three"":""ValueTwo""
}";
string result;
while (true)
{
result = Regex.Replace(json, @"(""[^.]+)(\.)(.+"":)", "$1_$3", RegexOptions.IgnoreCase);
if (json == result)
{
break;
}
json = result;
}
Console.WriteLine(result);
哪个会以您想要的方式输出结果:
{
"PropertyOne":{
"SubProperty_One":"SubValue.One"
},
"Property_Two_Three":"ValueTwo"
}
答案 2 :(得分:0)
实现所需目标的方法之一是尽早拦截序列化/反序列化过程,方法是重写JsonReader和JsonWriter。
public class CustomSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
throw new ArgumentNullException("value");
var properties = value.GetType().GetProperties();
writer.WriteStartObject();
foreach (var property in properties)
{
string propertyName = property.Name.Replace('.', '_');
// just write new property name and value
writer.WritePropertyName(propertyName);
writer.WriteValue(property.GetValue(value, new object[] { }));
}
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jsonObject = JObject.Load(reader);
List<JProperty> properties = jsonObject.Properties().ToList();
object instance = Activator.CreateInstance(objectType);
PropertyInfo[] objectProperties = objectType.GetProperties();
foreach (var objectProperty in objectProperties)
{
JProperty jsonProperty = properties.SingleOrDefault(prop => prop.Name == objectProperty.Name.Replace('_', '.'));
if (jsonProperty != null)
{
objectProperty.SetValue(instance, jsonProperty.Value.ToString(), new object[] { });
}
}
return instance;
}
public override bool CanConvert(Type objectType)
{
return true; // your logic here
}
}
和用法:
JsonConvert.SerializeObject(your_object, new CustomSerializer());