简体   繁体   English

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

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

I try to serialize C# objects to a JSON string and then send it over a network to a server.我尝试将 C# 对象序列化为 JSON 字符串,然后通过网络将其发送到服务器。 Yet the server never gets the obejcts.然而,服务器永远不会得到对象。 I tried to play with the settings of the JsonSerializer by setting the TypeNamehandling to Obejcts, but that didn't work too.我尝试通过将 TypeNamehandling 设置为 Obejcts 来使用 JsonSerializer 的设置,但这也不起作用。 I also don't like to convert the JSON-String to bytes and send it that way, because then I need to find some way to flush the NetworkStream I'm using and currently this Stream is always open.我也不喜欢将 JSON-String 转换为字节并以这种方式发送,因为我需要找到一些方法来刷新我正在使用的 NetworkStream,目前这个 Stream 始终是打开的。

I don't find any solution online.我在网上找不到任何解决方案。 I hope someone here can help me.我希望这里有人可以帮助我。 The whole code is uploaded to my GitHub!整个代码上传到我的 GitHub!

My Client Code:我的客户代码:

    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);
    }

My Server Code我的服务器代码

    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);
    }

And a message object looks like this一条消息 object 看起来像这样

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

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

Edit : Some more code from my Client, which shows how and with what I send the objects:编辑:来自我的客户的更多代码,显示了我发送对象的方式和方式:

 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();
    }

Edit 2 :编辑 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();
        }
    }

Found the solution.找到了解决方案。 The problem was, that my client never really sents the JSON data and my Server can't really recieve it, if the data was being sent.问题是,如果正在发送数据,我的客户端从未真正发送过 JSON 数据,而我的服务器无法真正接收到它。

The solution was rather simple.解决方案相当简单。 I just use an StreamWriter to sent the converted object.我只是使用StreamWriter发送转换后的 object。 It's important that I use the WriteLine -function, since that adds the Environment.NewLine -mark at the end of the package showing the server that this is the end of the package!我使用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);
        }
    }

For the recieving part I use the StreamReader with the function ReadLine .对于接收部分,我将StreamReader与 function ReadLine一起使用。 This function reads the stream used in the StreamReader until it sees the Environment.NewLine -mark.这个 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);
        }
    }

The only problem with this is, that the JsonConvert.DeserializeObject -function won't deserialize abstract objects or interfaces.唯一的问题是, JsonConvert.DeserializeObject函数不会反序列化抽象对象或接口。 For this you can watch this post!为此,您可以观看帖子!

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

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