繁体   English   中英

将 C# 对象序列化到 JSON 到服务器

[英]Serialize C# objects to a JSON to a server

我尝试将 C# 对象序列化为 JSON 字符串,然后通过网络将其发送到服务器。 然而,服务器永远不会得到对象。 我尝试通过将 TypeNamehandling 设置为 Obejcts 来使用 JsonSerializer 的设置,但这也不起作用。 我也不喜欢将 JSON-String 转换为字节并以这种方式发送,因为我需要找到一些方法来刷新我正在使用的 NetworkStream,目前这个 Stream 始终是打开的。

我在网上找不到任何解决方案。 我希望这里有人可以帮助我。 整个代码上传到我的 GitHub!

我的客户代码:

    public void Serialize(object value)
    {
        StreamWriter streamWriter = new StreamWriter(Stream);
        JsonWriter jsonWriter = new JsonTextWriter(streamWriter);
        jsonSerializer.Serialize(jsonWriter, value,typeof(Message));
    }

    public Message Deserialize()
    {
        StreamReader streamReader = new StreamReader(Stream);
        JsonReader jsonReader = new JsonTextReader(streamReader);
        return jsonSerializer.Deserialize<Message>(jsonReader);
    }

我的服务器代码

    public void Serialize(Stream stream, object value)
    {
        StreamWriter streamWriter = new StreamWriter(stream);
        JsonWriter jsonWriter = new JsonTextWriter(streamWriter);
        jsonSerializer.Serialize(jsonWriter, value,typeof(Message));
    }

    public Message Deserialize(Stream stream)
    {
        StreamReader streamReader = new StreamReader(stream);
        JsonReader jsonReader = new JsonTextReader(streamReader);
        return jsonSerializer.Deserialize<Message>(jsonReader);
    }

一条消息 object 看起来像这样

[Serializable]
public class StartupMessage : Message
{
    public string Username { get; set; }

    public StartupMessage(string username)
    {
        Username = username ?? throw new ArgumentNullException(nameof(username));
    }
}

编辑:来自我的客户的更多代码,显示了我发送对象的方式和方式:

 public string Username { get; }
    public string ServerIP { get; }
    //private readonly BinaryFormatter Formatter;
    private readonly JsonSerializer jsonSerializer;
    private readonly TcpClient Server;
    private readonly NetworkStream Stream;
    public event EventHandler<NewMessageEventArgs> NewMessage;

    public Client(string username, string serverIP)
    {
        Username = username ?? throw new ArgumentNullException(nameof(username));
        ServerIP = serverIP ?? throw new ArgumentNullException(nameof(serverIP));
        //Formatter = new BinaryFormatter();
        Server = new TcpClient(ServerIP, Message.Port);
        Stream = Server.GetStream();

        var settings = new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.Objects
        };
        jsonSerializer = JsonSerializer.Create(settings);
    }

    public void Start()
    {
        Serialize(new StartupMessage(Username));
        var recieverThread = new Thread(() =>
        {
            while (true)
            {
                Message msg = Deserialize();
                if(msg is ConnectedMessage)
                {
                    Console.WriteLine("Connected!");
                }
                if(msg is MessageMessage message)
                {
                    OnNewMessage(new NewMessageEventArgs(message.Message, message.Username));
                }
            }
        });
        recieverThread.Start();
    }

编辑 2

private readonly List<ClientInfo> clientInfos;
    //private readonly BinaryFormatter formatter;
    private readonly TcpListener tcpListener;
    private readonly JsonSerializer jsonSerializer;
    public EventHandler<NewMessageEventArgs> NewMessage;

    public Server()
    {
        clientInfos = new List<ClientInfo>();
        //formatter = new BinaryFormatter();
        tcpListener = new TcpListener(IPAddress.Any, Message.Port);
        var settings = new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.Objects
        };
        jsonSerializer = JsonSerializer.Create(settings);
    }

    public void Start()
    {
        while (true)
        {
            tcpListener.Start();
            TcpClient client = tcpListener.AcceptTcpClient();
            var recieverThread = new Thread(() =>
            {
                NetworkStream stream = client.GetStream();
                while (true)
                {

                    Message msg = Deserialize(stream);
                    if (msg is StartupMessage startup)
                    {
                        OnNewMessage(new NewMessageEventArgs("CONNECTED", startup.Username),true);
                        string username = startup.Username;
                        clientInfos.Add(new ClientInfo(username, stream));
                        Serialize(stream, new ConnectedMessage());
                    }
                    if (msg is MessageMessage message)
                    {
                        OnNewMessage(new NewMessageEventArgs(message.Message, message.Username),false);
                        foreach (ClientInfo info in clientInfos)
                        {
                            Serialize(info.Stream, message);
                        }
                    }
                }
            });
            recieverThread.Start();
        }
    }

找到了解决方案。 问题是,如果正在发送数据,我的客户端从未真正发送过 JSON 数据,而我的服务器无法真正接收到它。

解决方案相当简单。 我只是使用StreamWriter发送转换后的 object。 我使用WriteLine函数很重要,因为它在 package 的末尾添加了Environment.NewLine标记,向服务器显示这是包的结尾!

public void Serialize(Stream stream, Message value)
    {
        using (StreamWriter streamWriter = new StreamWriter(stream))
        {
            string json = JsonConvert.SerializeObject(value);
            streamWriter.WriteLine(json);
        }
    }

对于接收部分,我将StreamReader与 function ReadLine一起使用。 这个 function 读取StreamReader中使用的 stream 直到它看到Environment.NewLine -mark。

        public Message Deserialize(Stream stream)
    {
        using (StreamReader streamReader = new StreamReader(stream, true))
        {
            JsonReader jsonReader = new JsonTextReader(streamReader);
            string json = streamReader.ReadLine();
            return JsonConvert.DeserializeObject<Message>(json);
        }
    }

唯一的问题是, JsonConvert.DeserializeObject函数不会反序列化抽象对象或接口。 为此,您可以观看帖子!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM