我正在使用Newtonsoft JSON序列化程序,它适用于大多数对象。
不幸的是,JsonSerializationException
当我尝试序列化一个大对象时,我得到了一个,其中一个成员抛出NullReferenceException
。
无论如何,有没有要忽略有问题的成员并序列化对象的其余部分?
我在想JsonSerializerSettings
吗?
这是我想要做的简化版本:
private class TestExceptionThrowingClass
{
public string Name { get { return "The Name"; } }
public string Address { get { throw new NullReferenceException(); } }
public int Age { get { return 30; } }
}
[Test]
public void CanSerializeAClassWithAnExceptionThrowingMember()
{
// Arrange
var toSerialize = new TestExceptionThrowingClass();
// Act
var serializerSettings = new Newtonsoft.Json.JsonSerializerSettings();
serializerSettings.MaxDepth = 5;
serializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
serializerSettings.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
serializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
serializerSettings.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Reuse;
serializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
var result = Newtonsoft.Json.JsonConvert.SerializeObject(toSerialize);
// Assert
Assert.That(result, Is.EqualTo(@"{""Name"":""The Name"",""Age"":30}"));
}
这是堆栈跟踪:
at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, Formatting formatting, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value)
at AspectsProject.Aspects.CachingPolicy.CachingPolicyCacheKeyCreatorTests.CanSerializeAClassWithAnExceptionThrowingMember() in D:\Dev\test.cs:line 169
--NullReferenceException
at AspectsProject.Aspects.CachingPolicy.CachingPolicyCacheKeyCreatorTests.TestExceptionThrowingClass.get_Address() in D:\Dev\test.cs:line 149
at GetAddress(Object )
at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)
如果有人知道可以执行此操作,我很乐意使用其他JSON序列化程序。
如果您不控制源代码,则可以ContractResolver
在序列化过程中使用自定义为有问题的属性注入“
ShouldSerialize”方法。您可以使该方法始终返回false,或者可以选择实现一些逻辑,该逻辑将检测属性将仅在这种情况下抛出并返回false的情况。
例如,假设您的类如下所示:
class Problematic
{
public int Id { get; set; }
public string Name { get; set; }
public object Offender
{
get { throw new NullReferenceException(); }
}
}
显然,如果我们尝试序列化上述内容,它将无法正常工作,因为Offender
当序列化程序尝试访问该属性时,该属性始终会引发异常。由于我们知道引起问题的类和属性名称,因此我们可以编写一个自定义ContractResolver(派生自DefaultContractResolver)来抑制该特定成员的序列化。
class CustomResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member,
MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.DeclaringType == typeof(Problematic) &&
property.PropertyName == "Offender")
{
property.ShouldSerialize = instanceOfProblematic => false;
}
return property;
}
}
这是演示如何使用它的演示:
class Program
{
static void Main(string[] args)
{
Problematic obj = new Problematic
{
Id = 1,
Name = "Foo"
};
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CustomResolver();
string json = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine(json);
}
}
输出:
{"Id":1,"Name":"Foo"}
在您的评论中,您指出了当访问任何属性时,您可能会抛出多种异常的对象。为此,我们需要更通用的东西。这是一个可能适用于这种情况的解析器,但是您需要在自己的环境中进行广泛的测试。它不依赖于任何特定的类或属性名称,而是为
每个 以其方式出现的属性创建ShouldSerialize谓词。在该谓词中,它使用反射来获取try /
catch内的属性的值。如果成功,则返回true,否则返回false。
class CustomResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = instance =>
{
try
{
PropertyInfo prop = (PropertyInfo)member;
if (prop.CanRead)
{
prop.GetValue(instance, null);
return true;
}
}
catch
{
}
return false;
};
return property;
}
}
这是一个演示:
class Program
{
static void Main(string[] args)
{
List<MightThrow> list = new List<MightThrow>
{
new MightThrow { Flags = ThrowFlags.None, Name = "none throw" },
new MightThrow { Flags = ThrowFlags.A, Name = "A throws" },
new MightThrow { Flags = ThrowFlags.B, Name = "B throws" },
new MightThrow { Flags = ThrowFlags.Both, Name = "both throw" },
};
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CustomResolver();
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(list, settings);
Console.WriteLine(json);
}
}
[Flags]
enum ThrowFlags
{
None = 0,
A = 1,
B = 2,
Both = 3
}
class MightThrow
{
public string Name { get; set; }
public ThrowFlags Flags { get; set; }
public string A
{
get
{
if ((Flags & ThrowFlags.A) == ThrowFlags.A)
throw new Exception();
return "a";
}
}
public string B
{
get
{
if ((Flags & ThrowFlags.B) == ThrowFlags.B)
throw new Exception();
return "b";
}
}
}
输出:
[
{
"Name": "none throw",
"Flags": 0,
"A": "a",
"B": "b"
},
{
"Name": "A throws",
"Flags": 1,
"B": "b"
},
{
"Name": "B throws",
"Flags": 2,
"A": "a"
},
{
"Name": "both throw",
"Flags": 3
}
]
有没有一种方法让我忽略这些异常并在消费者处移动偏移量?我想,因为我使用手动偏移提交,我有这个问题。有人知道如何配置kafka-avro-serializer-6.0.0.jar来完成我想要的任务吗? 多谢了。
问题内容: 我有一些扩展的模型类:它们定义用于包装Map的get和put方法的getter和setter。我正在尝试使用Jackson(带有RESTEasy)序列化这些类的实例,但是Jackson拒绝注意我的getter(使用注释)。而是仅序列化支持映射的键- 值对。我尝试使用禁用所有方法和字段的自动检测功能,但这并没有任何改变。有没有办法防止Jackson序列化Map,还是必须创建不扩展的新模型
我正在尝试反序列化以下JSON: 通过此方法调用: 方法: 不幸的是,我得到了以下错误: System.Text.Json.JsonException:'JSON 值无法转换为 System.DateTime。路径:$。出版|行号: 0 |BytePositionInLine: 353.' JSON 来自对以下 API 方法的调用: 是正常的 属性 我做错了什么?如何将JSON的<code>pub
问题内容: 我使用以下代码来序列化从外部服务获得的响应,并作为我的服务的一部分返回json响应。但是,当外部服务返回带有时区(10:30:00.000-05.00)的时间值时,杰克逊会将其转换为15:30:00。如何忽略时区值? 问题答案: 您可以创建自定义解串器 告诉杰克逊使用您的自定义解串器 并像这样使用它: 您可以使用Jackson自定义序列化为服务响应添加时区信息
我使用Spring并创建了一个REST服务。 这是我的控制器的一部分: 该人员的角色是延迟初始化的,当时不需要。当(1)被注释掉时,所有操作都将失败 org.springframework.http.converter.HttpMessageNotWritableException:无法写入JSON:无法延迟初始化角色集合:no.something.project.Person.roles,无法初
问题内容: 我有一组linq到sql类,并使用.NET JavaScriptSerializer将它们序列化为JSON。 但是,一旦我将记录添加到相关表上,序列化就会引发“循环引用异常”。啊! 在这里详细描述。 我有几种选择 将linq to sql类转换为没有关系的类,从而避免循环引用 通过取消关联来剪断循环引用-我不认为这是一个真实的选择 使用ScriptIgnoreAttribute(以某种