我有一个类属性集,并在构造函数中固定,下面的示例是一个Guid.NewGuid()..
理由是只允许类在创建时填充..所以它在构造函数中设置,并且只标记为get;- 工作正常,直到我序列化/反序列化为 Json。
似乎因为没有set;反序列化失败..并且构造函数介入并创建了一个新的guid
我已经尝试过内部、私有和受保护的 set .. 但所有结果都导致属性的再生,我可以让它工作的唯一方法是将 Id 标记为{get;set;},
class Foo
{
public Foo() => Id = Guid.NewGuid().ToString();
public string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这意味着您可以简单地执行以下操作:
var obj = new Foo();
obj.Id = "Any Old Rubbish";
Run Code Online (Sandbox Code Playgroud)
有没有办法解决这个问题?
短样本:
class Program
{
static void Main()
{
var obj = new Foo();
Console.WriteLine(obj.Id);
var serialize = JsonConvert.SerializeObject(obj);
var deserialize = JsonConvert.DeserializeObject<Foo>(serialize);
Console.WriteLine(deserialize.Id);
Console.ReadLine();
}
}
class Foo
{
public Foo() => …Run Code Online (Sandbox Code Playgroud) 我正在研究SignalR的一个项目,我有一些我将要通过它的对象.这些对象只在我的后端代码中显式创建,我真的希望能够对它们强制实现不变性和不变量.我遇到了SignalR要求我(好吧,实际上是NewtonSoft.Json)的问题,在我的属性上有一个默认的,无参数的构造函数和公共setter,以便它通过网络序列化和反序列化它们.
这是一个人为的例子:
public class Message{
public string Text {get;set;}
public int Awesomeness {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
我想要的是,更多的是这些内容(它应该只有readonly私有字段和getter-only属性完全不可变,但对于只有POCO而没有方法的东西,足够好)
public class Message {
public string Text {get;private set;}
public int Awesomeness {get;private set;}
public Message( string msg, int awesome){
if (awesome < 1 || awesome > 5){
throw new ArgumentOutOfRangeException("awesome");
}
Text = msg;
Awesomeness = awesome;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我这样做,我的对象不能被SignalR .NET客户端库反序列化.我可以在那里查找一个默认构造函数,然后公开我的setter,但是我必须记住不要在我的代码中使用它们,并确保团队中没有其他人在不理解的情况下使用它们.
我已经开始尝试这样做,将默认构造函数标记为永远不应该显式使用的东西:
[Obsolete("Bad! don't do this!")
public Message(){}
Run Code Online (Sandbox Code Playgroud)
但是我不能仅仅在属性的setter上使用Obsolete属性.
如果我真的想要,我可以从DTO表示中分离出"真实"对象并在它们之间进行转换,但是我真的很兴奋写一堆样板来做这件事并引入另一层.
有什么我忽略的,或者我只需要咬紧牙关并处理它?
考虑包含如下列表值的 F# 记录:
type MyRecord = {
Name: string
SomeList: string list
}
Run Code Online (Sandbox Code Playgroud)
Netwonsoft.Json.JsonConvert当 JSON 不包含记录的列表值的属性时,使用将 JSON 反序列化为Values该记录将导致反序列化的记录具有null列表的值而不是空列表[]。
那是,
open Newtonsoft.Json
JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Some name"}""" ) |> printfn "%A"
// Gives: { Name = "Some name"; SomeList = null; }
Run Code Online (Sandbox Code Playgroud)
如何反序列化 usingNetwonsoft.Json以使列表初始化为空列表?例如:
{ Name = "Some name"; SomeList = []; }
Run Code Online (Sandbox Code Playgroud) 可以这样调整JsonSerializerSettings吗?
(我猜不是)但仍有一些希望,因为我对他们的API不是很有经验.
默认情况下,我尝试丢失的所有设置都反序列化为0或导致异常.
例
{
"defaultCaptionLineNum": 6,
"worksheets": {
"0": { "name": "Ws1", "caption_ln": 6 },
"1": { "name": "Ws2", "caption_ln": null },
"2": { "name": "Ws3" },
"3": { "name": "Ws4", "caption_ln": 5 },
}
}
Run Code Online (Sandbox Code Playgroud)
目前默认情况下,Ws3的标题行(caption_ln)计算为0,我希望将其计算为null(如Ws2中所示).
我正在使用
jObject.ToObject<MyClass>(JsonSerializer.Create(settings));
Run Code Online (Sandbox Code Playgroud)
从JSON获取带有工作表(Ws)信息的对象(在没有序列化器的情况下尝试了它)
和任何变化Include,并Ignore在这里不作jObject在反序列化JSON缺少整数不同(与抛误差除外马上遗漏值)
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include,
MissingMemberHandling = MissingMemberHandling.Ignore
};
Run Code Online (Sandbox Code Playgroud)
其他串行器设置似乎无关紧要.
UPD:MyObject MyClass的列表.
public class MyClass
{
public class WorkSheet
{
[JsonProperty("name")]
string wsName;
[JsonProperty("caption_ln")]
int? captionLineNumber;
public WorkSheet(string name, …Run Code Online (Sandbox Code Playgroud)