对象转成json后转成byte[]后在转成string会提示序列化失败,第一个字符是问号

问题复现

一个对象需要转成json 后转成byte[]后经过网络传输,后再次反序列化为对象,但是最后反序列的时候会报错,打印json发现开头是一个问号

省流

使用这个进行反序列化

     /// <summary>
     /// 反序列化方法
     /// </summary>
     /// <typeparam name="T"></typeparam>
     /// <param name="json"></param>
     /// <returns></returns>
     public static T Deserialize<T>(string json) where T : Message, new()
     {
         return JsonConvert.DeserializeObject<T>(json.TrimStart('\uFEFF'));

     }

问题代码

一个对象

using System.Threading;

namespace SocketTools
{
    public class TextMessage : Message
    {

        private string message;

        public string Message { get => message; set => message = value; }

        public TextMessage()
        {

        }


        public TextMessage(string userName, string targetName, string sendTime, string message) : base(userName, targetName, sendTime, MessageType.Text)
        {
            this.message = message;
        }
    }

父类



using Newtonsoft.Json;

namespace SocketTools
{

    public enum MessageType
    {
        Connection = 0,
        Text,
        Image,
        Mixed,
        Recall,
        File,

    }

    public class Message
    {
        private string userName;
        private string targetName;
        private string sendTime;
        private MessageType messageType;

        public string UserName { get => userName; set => userName = value; }
        public string TargetName { get => targetName; set => targetName = value; }
        public string SendTime { get => sendTime; set => sendTime = value; }
        public MessageType MessageType { get => messageType; set => messageType = value; }

        public Message()
        {

        }

        public Message(string userName, string targetName, string sendTime, MessageType messageType)
        {
            UserName = userName;
            TargetName = targetName;
            SendTime = sendTime;
            MessageType = messageType;
        }

       // 序列化方法
       public static string Serialize(Message message)
       {
           return JsonConvert.SerializeObject(message);
       }

       // 反序列化方法
       public static T Deserialize<T>(string json) where T : Message, new()
       { 
   return JsonConvert.DeserializeObject<T>(json );
  
       }
     

    }

}

}

执行代码

using SocketTools;
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace FunctionalTesting
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string msg = "消息内容Q1_2_end";
            string userName = "AAAAAAAAAAAAAAAA";
            string targetUserName = "CCCCCCCCCCCCCCCC";


            TextMessage textMessage = new TextMessage(userName,
                targetUserName,
                DateTime.Now.ToString("yy-MM-dd-H:m:s"),
                msg);

            // 按照指定的格式创建消息字符串
            string message = Message.Serialize(textMessage);
            Console.WriteLine(message);
            // 将消息字符串转换为字节流
            byte[] data;
            using (MemoryStream ms = new MemoryStream())
            {
                using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8))
                {
                    sw.Write(message);
                    sw.Flush();
                    ms.Position = 0;
                    data = ms.ToArray();
                }
            }
            string data2 = Encoding.UTF8.GetString(data);
            Console.WriteLine(data2);
            data2 = Regex.Replace(data2, @"^\s+", "");
            Console.WriteLine(data2);

            var d = Message.Deserialize<TextMessage>(data2);
            Console.WriteLine(d.TargetName);
            Console.WriteLine(d.UserName);
            Console.WriteLine(d.MessageType);
            Console.ReadLine();

        }
    }
}


执行后的效果

执行之后会输出

?{"Message":"消息内容Q1_2_end","UserName":"AAAAAAAAAAAAAAAA","TargetName":"CCCCCCCCCCCCCCCC","SendTime":"23-12-04-1:14:43","MessageType":1}

错误日志:

Newtonsoft.Json.JsonReaderException
  HResult=0x80131500
  Message=Unexpected character encountered while parsing value: . Path '', line 0, position 0.

但是打印原本的数据是没有开头的问号的,

解决方式

修改反序列化的代码,去除第一个前导字符即可,或者使用字符串的判断,如果第一个字符不是{或者[ 就去除第一个字符

  // 反序列化方法
      public static T Deserialize<T>(string json) where T : Message, new()
      { 
     return JsonConvert.DeserializeObject<T>(json.TrimStart('\uFEFF'));
 
      }

去除字符串

      public static T Deserialize<T>(string json) where T : Message, new()
      { 
          if (json[0] == '{' || json[0] == '[')
          {
          }
          else
          {
              json = json.Remove(0, 1);
          }
          return JsonConvert.DeserializeObject<T>(json);
      }

问题原因

零宽度不中断空格(Unicode U+FEFF)字符,也称为 BOM(Byte Order Mark),在文本文件中用于表示字节顺序。它通常出现在使用 Unicode 编码的文本文件或数据流的开头。

在处理多字节编码时,需要知道每个字符的字节顺序。例如,在 UTF-16 编码中,一个字符由两个字节组成,而这两个字节的顺序可能会根据不同的系统和平台有所不同。为了明确表示字节顺序,引入了 BOM 字符。

BOM 字符 U+FEFF 可以作为文件的前导字符,允许解析器识别文件的字节顺序。当解析器遇到 U+FEFF 时,它可以确定字节顺序并正确地解码文件中的其余字符。

在某些情况下,尤其是在网络通信、数据库存储或其他形式的数据交换中,BOM 字符可能被无意间包含在字符串中,这可能导致解析错误。因此,有必要在处理这些字符串之前检查并移除任何不需要的 BOM 字符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值