You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用DataContractJsonSerializer序列化JSON出现尾随空字符致单元测试失败

解决DataContractJsonSerializer序列化JSON出现尾随空字符导致单元测试失败的问题

问题重现

你在使用DataContractJsonSerializer序列化Currency对象时,生成的JSON字符串带有大量尾随空字符(\0),导致单元测试对比文件中的示例JSON时失败。虽然带空字符的JSON能正常反序列化,但严格的字符串对比无法通过。

相关代码如下:

原始序列化代码

public static string SerializeJSON<T>(T ObjectToSerialize) {
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(ObjectToSerialize.GetType());
    using (MemoryStream memoryStream = new MemoryStream()) {
        using (var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, Encoding.UTF8, false, true)) {
            serializer.WriteObject(jsonWriter, ObjectToSerialize);
        }
        return Encoding.UTF8.GetString(memoryStream.GetBuffer());
    }
}

单元测试代码

[TestMethod]
public void SerializeJSON() {
    string testJSON = File.ReadAllText(@"Util\\TestCurrency.json");
    Currency currency = StaticExamples.ccy1;
    string json = SerializeUtil.SerializeJSON(currency);
    Assert.AreEqual(testJSON, json);
}

Currency类定义

public class Currency {
    public int currencyId { get; set; }
    public string code { get; set; }
    public string name { get; set; }
    public string status { get; set; }
}

问题根源

问题出在memoryStream.GetBuffer()这个方法上:它返回的是内存流整个预分配的底层缓冲区,而不是实际写入的有效数据。内存流会提前分配比实际需要更大的空间,未被使用的缓冲区部分会被填充为空字符(\0),所以转换成字符串后就会带有这些多余的尾随空字符。

修复方案

我们需要只读取内存流中实际写入的有效数据,有两种常用的方式:

方式一:使用StreamReader读取(你已经采用的方案)

将流的位置重置到起始处,然后用StreamReader读取所有有效数据:

public static string SerializeJSON<T>(T ObjectToSerialize) {
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(ObjectToSerialize.GetType());
    using (MemoryStream memoryStream = new MemoryStream()) {
        using (var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, Encoding.UTF8, false, true)) {
            serializer.WriteObject(jsonWriter, ObjectToSerialize);
        }
        memoryStream.Position = 0; // 重置流指针到开头
        return new StreamReader(memoryStream).ReadToEnd(); // 仅读取有效数据
    }
}

方式二:使用ToArray()获取有效字节数组

memoryStream.ToArray()会返回仅包含实际写入数据的字节数组,再转换为字符串:

public static string SerializeJSON<T>(T ObjectToSerialize) {
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(ObjectToSerialize.GetType());
    using (MemoryStream memoryStream = new MemoryStream()) {
        using (var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, Encoding.UTF8, false, true)) {
            serializer.WriteObject(jsonWriter, ObjectToSerialize);
        }
        return Encoding.UTF8.GetString(memoryStream.ToArray()); // 仅转换有效数据
    }
}

这两种方式都能避免读取缓冲区中的空字符,生成的JSON字符串就会和文件中的示例完全一致,单元测试就能顺利通过了。

内容的提问来源于stack exchange,提问作者Erik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:33:48