- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试创建一个 IContractResolver 来简化我在 WebApi 项目上的安全处理。
我正在尝试:
我想根据一组动态条件(例如调用端点的用户的角色)序列化某些对象/属性。
所以我实现了一个自定义属性,该属性在接口(interface)的 CreateProperty 重写中被选中,并将 ShouldSerialize 函数设置为我自己的逻辑。
我现在的问题是,是否可以有条件地序列化某个列表中的完整对象?我希望当前的 ContractResolver 递归处理它,而不是在预处理步骤中过滤列表(这很容易出错,如果我更改我的对象)。
在某种程度上,我试图得到这样的东西:
override void CreateObject(JSONObject ob){
if ( ob.DeclaringType == MyType)
{
ob.ShouldSerialize = instance => {[...] }; //Custom Logic
}
}
我是否缺少覆盖,这根本不可能吗?有没有更好的方法来实际执行此操作,而无需“预解析”我所有的值?
最佳答案
这不是开箱即用的。如果您检查 JsonSerializerInternalWriter.SerializeList()
的来源您会看到没有逻辑可以根据某些过滤器跳过集合条目。
但是,Json.NET 确实有 robust exception handling .如果在开始序列化对象时抛出异常,则在 [OnError]
中捕获并吞噬回调:
null
。因此,实现所需功能的一种可能性是从添加到 JsonContract.OnSerializingCallbacks
的人工回调中抛出异常。通过您的自定义契约(Contract)解析器,然后使用添加到 JsonContract.OnErrorCallbacks
的处理程序捕获并吞下异常.当与您已经在做的属性值过滤相结合时,这种方法的优点是保证 secret 对象不能被序列化,即使它是根对象或包含在字典、动态对象或多维数组中也是如此。这种方法不会干扰 PreserveReferencesHandling.Arrays
.
执行此操作的一个契约(Contract)解析器如下:
sealed class JsonSkipObjectException : JsonException
{
}
public class ShouldSerializeContractResolver : DefaultContractResolver
{
readonly Predicate<object> shouldSerialize;
readonly SerializationCallback serializationCallback;
readonly SerializationErrorCallback onErrorCallback;
public ShouldSerializeContractResolver(Predicate<object> shouldSerialize)
: base()
{
this.shouldSerialize = shouldSerialize;
this.serializationCallback = (o, context) =>
{
if (shouldSerialize != null && !this.shouldSerialize(o))
throw new JsonSkipObjectException();
};
this.onErrorCallback = (o, context, errorContext) =>
{
if (errorContext.Error is JsonSkipObjectException)
{
errorContext.Handled = true;
}
};
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (shouldSerialize != null)
{
if (property.Readable)
{
var oldShouldSerialize = property.ShouldSerialize;
property.ShouldSerialize = (o) =>
{
if (oldShouldSerialize != null && !oldShouldSerialize(o))
return false;
var value = property.ValueProvider.GetValue(o);
if (!this.shouldSerialize(value))
return false;
return true;
};
}
}
return property;
}
protected override JsonContract CreateContract(Type objectType)
{
var contract = base.CreateContract(objectType);
contract.OnSerializingCallbacks.Add(serializationCallback);
contract.OnErrorCallbacks.Add(onErrorCallback);
return contract;
}
}
那么一种可能的用途是:
public interface IConditionalSerialization
{
bool ShouldSerialize();
}
public class ConditionalSerializationObject : IConditionalSerialization
{
public bool IsSecret { get; set; }
public string SecretProperty { get { return "should not see me"; } }
// Ensure "normal" conditional property serialization is not broken
public bool ShouldSerializeSecretProperty()
{
return false;
}
#region IConditionalSerialization Members
bool IConditionalSerialization.ShouldSerialize()
{
return !IsSecret;
}
#endregion
}
public class TestClass
{
public static void Test()
{
Predicate<object> filter = (o) =>
{
var conditional = o as IConditionalSerialization;
return conditional == null || conditional.ShouldSerialize();
};
var settings = new JsonSerializerSettings
{
ContractResolver = new ShouldSerializeContractResolver(filter),
};
var ok = new ConditionalSerializationObject { IsSecret = false };
var notOk = new ConditionalSerializationObject { IsSecret = true };
Test(ok, settings);
Test(new { Public = ok, Private = notOk }, settings);
Test(new [] { ok, notOk, ok, notOk }, settings);
Test(new[,] {{ ok, notOk, ok, notOk }}, settings);
Test(new { Array = new[,] { { ok, notOk, ok, notOk } } }, settings);
try
{
Test(notOk, settings);
}
catch (Exception ex)
{
Console.WriteLine("Exception thrown and not caught serializing root object " + notOk.GetType());
Console.WriteLine(ex);
}
}
static void Test<T>(T value, JsonSerializerSettings settings)
{
Console.WriteLine("Unfiltered object: ");
Console.WriteLine(JToken.FromObject(value));
var serializer = JsonSerializer.CreateDefault(settings);
var token = JToken.FromObject(value, serializer);
Console.WriteLine("Filtered object: ");
Console.WriteLine(token);
if (!token.SelectTokens("..IsSecret").All(t => JToken.DeepEquals(t, (JValue)false)))
{
throw new InvalidOperationException("token.SelectTokens(\"..IsSecret\").All(t => JToken.DeepEquals(t, (JValue)true))");
}
if (token.SelectTokens("..SecretProperty").Any())
{
throw new InvalidOperationException("token.SelectTokens(\"..SecretProperty\").Any()");
}
Console.WriteLine("Secret objects and properties were successfully filtered.");
Console.WriteLine("");
}
}
原型(prototype) fiddle .
请注意,抛出和捕获大量异常可能会对性能产生影响。参见 How expensive are exceptions in C#? .您将需要分析您的 Web 应用程序以确定这是否是一个问题。您还需要决定您的 Web 服务在尝试序列化“ secret ”根对象时是否应该返回异常,或者做一些不同的事情。
关于c# - JSON.Net 自定义合约序列化和集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38038793/
我遇到了 following code : contract="*" 是什么意思? 不是每个 WCF 客户端或服务都必须指定契约(Contract)吗? 最佳答案 它用于服
我想通过 web3 用 pancakeswap testnet contarct 将一些 testnet bep20 token 交换到 busd(bep20)。 我查看了契约(Contract),但
我创建了 WCF 服务应用程序,在运行 WcfTestClient 之前没有错误.它需要 IMetadataExchange进行配置。 如何配置IMetadataExchange或避免使用? 错误:
我对 Kotlin 可空性有疑问,我想知道我是否能够通过契约(Contract)解决它。 对于这样的Java接口(interface):interface Action{ void execute(T
我有两个需要受契约(Contract)约束的 .NET 方。现在,party1 和 party2 需要能够相互调用一些方法(大部分是调用和报告结果)。我有双工契约(Contract),但双方没有使用
Scrapy 合约问题 我开始研究 scrapy 框架。也实现了一些蜘蛛 提取,但我无法为蜘蛛编写单元测试用例,因为契约(Contract) scrapy 提供的包文档没有正确的程序来编写 测试用例。
简而言之,hashCode合约,根据Java的object.hashCode(): 除非影响 equals() 的内容发生更改,否则哈希码不应更改 equals() 表示哈希码是 == 让我们假设主要
从 web3js 传递(javascript 对象数组)时出现错误, 以(结构数组)为参数的solidity函数。 你可以帮帮我吗? 下面是代码和错误 // web3js code let slcte
使用Spring云合约来验证我的生产者和消费者之间的合约。在我的消费者 Controller 中,我使用 Feign 客户端调用另一个微服务方法来获取一些数据。但现在在 Spring Cloud 合约
我正在尝试让一个简单的基于 Acumatica 契约的 SOAP API Get() 或 GetList() 调用工作,但我得到的只是一个错误: System.ServiceModel.FaultEx
关于如何为使用 @RequestBody 注释并以字符串集合作为参数的方法编写契约的问题。我有以下方法: @PostMapping(path = "/some/uri", produces =
Wiremock 记录以下请求不匹配: WireMock : Request was not matched: { "url
通常我通过导入外部契约(Contract)的接口(interface)并生成契约(Contract)的“局部变量”来调用外部契约(Contract),一旦我需要它。像这样的东西: import "./
我正在尝试编写一个断言函数来检查给定对象是否属于 T 类型: @UseExperimental(ExperimentalContracts::class) inline fun assertIsIn
当我使用 gradle 构建项目时,我不断收到 Spring Cloud Contract 的此错误。有什么线索吗? * What went wrong: Execution failed for t
我尝试创建一个 MQL4 脚本(一种几乎与 C++ 相关的语言,MQL4),我想在其中将 double 值分为 9 个部分,其中分数不相等,但增加 我当前的代码尝试这样做(伪代码): Lots1
背景 我在 Solidity 中编写了一个以太坊智能合约语言。为了进行测试,我可以使用 Ganache 运行本地节点并使用 truffle migrate 在其上部署我的合约。 要求 我想使用 Jav
我正在尝试将 Spring 契约(Contract) stub jar 设置为带有使用者的胖 jar 或我的服务可以向其发送请求并最终接收评估响应的 http REST 端点。 理想情况下,我更喜欢后
我是 DAML 新手,我想使用 Java 绑定(bind)、Bot API 查询所有 Activity 合约,并将它们保存到数据库(或内存中)以供将来查询。 根据文档,LedgerView 可以跟踪内
我遇到了“您尚未配置 MockMVC 实例”的问题。 “mvn全新安装”时的异常。 运行 org.springframework.cloud.contract.verifier.tests.Contr
我是一名优秀的程序员,十分优秀!