【问题标题】:Serialize and deserialize part of JSON object as string with WCF使用 WCF 将 JSON 对象的一部分序列化和反序列化为字符串
【发布时间】:2015-06-04 20:30:40
【问题描述】:

我有一个 WCF REST 服务,它有一个包含多个类型字段的资源,然后是一个可以是对象数组的字段。我希望我们服务上的字段序列化这个字段,就好像它是一个字符串一样。示例:

[DataContract]
public class User
{
   [DataMember]
   public long ID;

   [DataMember]
   public string Logon;

   [DataMember]
   public string Features; 
}

当我们 API 的用户发布一个新的用户对象时,我希望他们能够使用这样的东西作为主体:

{
    "ID" : 123434,
    "Logon" : "MyLogon",
    "Features" : [ 
           { "type": "bigFeature", "size": 234, "display":true },
           { "type": "smFeature", "windowCount": 234, "enableTallness": true}
     ]
 }

而不是

{
    "ID" : 123434,
    "Logon" : "MyLogon",
    "Features" : "[ 
           { \"type\": \"bigFeature\", \"size\": 234, \"display\":true },
           { \"type\": \"smFeature\", \"windowCount\": 234, \"enableTallness\": true}
     ]"
 }

在服务方面,我将把“Features”数组作为 JSON 文本博客保存在数据库中,当我在 GET 调用中返回对象时,我希望它能够正确往返。

【问题讨论】:

  • 所以您想获取您的 JSON 字符串,然后能够通过函数调用对其进行序列化/反序列化?
  • 不,我想使用 DataContract 和 DataMember 来定义数据,但我希望其中一个字段实际上是 JSON 数组,这将允许它包含任何 JSON 对象。这样我就可以来回转换了。
  • 你使用的是什么序列化程序 -- DataContractJsonSerializer 或 Json.NET?
  • DataContractJsonSerializer,我考虑过切换 Json.NET,但我记得有问题。您是否认为使用 Json.NET 序列化程序可以实现这一点?
  • 使用 Json.NET 会更容易。 DataContractJsonSerializerDataContractSerializer 共享一个用于 XML 的代码库(两者都继承自 XmlObjectSerializer)并且据我所知不提供对“原始”JSON 的访问权限。

标签: c# json wcf serialization


【解决方案1】:

如果您愿意切换到 Json.NET,您可以将您的 Features 字符串序列化为私有 JToken 代理属性:

[DataContract]
public class User
{
    [DataMember]
    public long ID;

    [DataMember]
    public string Logon;

    string _features = null;

    [IgnoreDataMember]
    public string Features
    {
        get
        {
            return _features;
        }
        set
        {
            if (value == null)
                _features = null;
            else
            {
                JToken.Parse(value); // Throws an exception on invalid JSON.
                _features = value;
            }
        }
    }

    [DataMember(Name="Features")]
    JToken FeaturesJson
    {
        get
        {
            if (Features == null)
                return null;
            return JToken.Parse(Features);
        }
        set
        {
            if (value == null)
                Features = null;
            else
                Features = value.ToString(Formatting.Indented); // Or Formatting.None, if you prefer.
        }
    }
}

请注意,为了序列化 Features 字符串而不转义,它必须是有效的 JSON,否则您的外部 JSON 将被损坏。我在设置器中强制执行此操作。如果您愿意,可以使用 JArray 而不是 JToken 来强制要求字符串表示 JSON 数组。

请注意,在序列化过程中不会保留字符串格式。

【讨论】:

  • 我尝试使用 JToken 作为 DataMember,但出现反序列化异常:“Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract which is not supported. 请考虑修改定义集合 'Newtonsoft.Json.Linq.JToken' 以删除对自身的引用。”,我想我需要从使用 DataContractJsonSerializer 切换到 Newtonsoft,但我还没有找到一个很好的例子来说明如何做到这一点。
  • 第一篇文章需要改变你所有的DataContracts来返回Message或者Stream,我不太喜欢。第二个指向这篇文章,我不久前看到了,但代码甚至从未正确编译:blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/…
  • 看起来像使用 carlogsfigureira 博客中的代码示例和 msdn 示例未能注意到它们不适用于我广泛使用的 UriTemplates。您是否获得了使用 UriTemplates 的代码?它适用于我的 POST 请求,但我的 GET 和 DELETE 请求需要它们。
  • 它们可以是任何有效的 json。使用 SimpleDictionary 的自定义序列化是不够的。
猜你喜欢
  • 1970-01-01
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 2020-02-03
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
相关资源
最近更新 更多