[英]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.