簡體   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