【问题标题】:How can I make DataContractJsonSerializer serialize an object as a string?如何使 DataContractJsonSerializer 将对象序列化为字符串?
【发布时间】:2009-07-24 14:59:46
【问题描述】:

我在 C# 中有一个包含 guid 的结构。我正在使用 DataContractJsonSerializer 来序列化包含该类实例的对象。当我直接使用 guid 时,它被序列化为纯字符串,但现在它被序列化为名称/值对。这是一个演示问题的 NUnit 测试和支持代码:

    private static string ToJson<T>(T data)
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof (T));

        using (MemoryStream ms = new MemoryStream())
        {
            serializer.WriteObject(ms, data);
            return Encoding.Default.GetString(ms.ToArray());
        }
    }

    [Serializable]
    private class ID
    {
        private Guid _value;

        public static explicit operator ID(Guid id)
        {
            return new ID { _value = id };
        }

        public static explicit operator Guid(ID id)
        {
            return id._value;
        }
    }

    [Test]
    public void IDShouldSerializeLikeGuid()
    {
        Guid guid = Guid.NewGuid();
        ID id = (ID) guid;
        Assert.That(ToJson(id), Is.EqualTo(ToJson(guid)));
    }

以及测试运行器输出:

NUnit.Framework.AssertionException:   Expected string length 38 but was 49. Strings differ at index 0.
  Expected: ""7511fb9f-3515-4e95-9a04-06580753527d""
  But was:  "{"_value":"7511fb9f-3515-4e95-9a04-06580753527d"}"
  -----------^

如何将我的结构序列化为纯字符串并让我的测试通过?

【问题讨论】:

    标签: c# .net json datacontractserializer


    【解决方案1】:

    在这种情况下,您似乎并不真正想要 JSON,您想要一个字符串表示。在这种情况下,我会创建一个这样的界面:

    interface IStringSerialized
    {
        String GetString();
    }
    

    在您的 ID 类型(以及具有类似要求的所有其他类型)上实现此接口。

    [Serializable]
    class ID : IStringSerialized
    {
        private Guid _value;
    
        public static explicit operator ID(Guid id)
        {
            return new ID { _value = id };
        }
    
        public static explicit operator Guid(ID id)
        {
            return id._value;
        }
    
        public string GetString()
        {
            return this._value.ToString();
        }
    }
    

    然后修改你的序列化方法来处理这些特殊情况:

    private static string ToJson<T>(T data)
    {
        IStringSerialized s = data as IStringSerialized;
    
        if (s != null)
            return s.GetString();
    
        DataContractJsonSerializer serializer 
                    = new DataContractJsonSerializer(typeof(T));
    
        using (MemoryStream ms = new MemoryStream())
        {
            serializer.WriteObject(ms, data);
            return Encoding.Default.GetString(ms.ToArray());
        }
    }
    

    【讨论】:

    • 我省略了一些复杂性以使问题清晰,但在实际应用程序中,这是在其中包含 List 的包含对象的上下文中。我希望真正的代码产生 ["guid1", "guid2"],而不是 [{"_value": "guid1"}, {"_value": "guid2"}]。所以不幸的是,这种方法对我不起作用。不过感谢您的想法!
    • 不要使用默认编码,因为它会损坏任何非 ANSI 字符。我目前正在处理手机推送消息。您的代码应该能够处理其他语言。请改用 UTF8。 return Encoding.UTF8.GetString(ms.ToArray());
    【解决方案2】:

    尝试使用JavaScriptSerializer 类,它将防止键值膨胀问题。

    【讨论】:

    • 但是您将丢失您想要序列化的对象中的所有数据协定属性(例如 emitdefaultvalue)
    猜你喜欢
    • 2015-11-06
    • 2013-12-31
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 2011-01-26
    相关资源
    最近更新 更多