1

DataContractJsonSerializer将 OData 实体发布到支持多种实体类型(每个表的层次结构)的集合中时,是否有办法发出所需的“odata.type”字段?

如果我使用设置为DataContractJsonSerializer的设置对象进行构造,它会在输出中发出一个“__type”字段,但这不是 OData 所需的字段名称,并且值的格式也是错误的。EmitTypeInformationAlways

有什么方法可以挂钩DataContractJsonSerializer管道以将所需的“odata.type”字段注入序列化输出?

必须解析序列化输出才能注入该字段,这将是一种黑客行为。WCF 数据服务是如何做到的?不使用DataContractJsonSerializer是我的猜测。

4

2 回答 2

0

我无法回答您的前两个问题,但对于第三个问题,我在OData 团队博客上找到了指向OData WCF 数据服务 V4 库开源代码的链接。下载该代码,您将看到它们手动执行所有序列化和反序列化。他们的两个 Json 文件夹中有 68 个文件!并查看代码,他们有如下评论:

// This is a work around, needTypeOnWire always = true for client side: 
// ClientEdmModel's reflection can't know a property is open type even if it is, so here 
// make client side always write 'odata.type' for enum.

所以这对我来说意味着没有简单、干净、简单、优雅的方式来做到这一点。

我尝试使用 a JavaScriptConverter、 adynamic类型和其他东西,但他们中的大多数最终都求助于使用 Reflection ,与仅使用字符串操作方法相比,这只是一个更复杂的解决方案。

于 2014-10-17T17:47:50.990 回答
0

你考虑过使用Json.Net吗?Json.Net 更具可扩展性,您可以使用自定义解析器来完成您所拥有的场景。示例代码

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(
            JsonConvert.SerializeObject(new Customer { Name = "Raghu" }, new JsonSerializerSettings
            {
                ContractResolver = new CustomContractResolver()
            }));
    }
}

public class CustomContractResolver : DefaultContractResolver
{
    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        JsonObjectContract objectContract = base.CreateObjectContract(objectType);
        objectContract.Properties.Add(new JsonProperty
        {
            PropertyName = "odata.type",
            PropertyType = typeof(string),
            ValueProvider = new StaticValueProvider(objectType.FullName),
            Readable = true
        });

        return objectContract;
    }

    private class StaticValueProvider : IValueProvider
    {
        private readonly object _value;

        public StaticValueProvider(object value)
        {
            _value = value;
        }

        public object GetValue(object target)
        {
            return _value;
        }

        public void SetValue(object target, object value)
        {
            throw new NotSupportedException();
        }
    }
}

public class Customer
{
    public string Name { get; set; }
}
于 2013-08-22T18:56:00.923 回答