相关疑难解决方法(0)

JSON.net ContractResolver与JsonConverter

我已经和JSON.net合作了一段时间.我已经编写了自定义转换器和自定义合同解析器(通常来自修改SO和Newtonsoft网站上的示例),它们工作正常.

除了例子之外,我面临的挑战是,我什么时候应该使用其中一个(或两个)进行处理.根据我自己的经验,我基本上已经确定合同解决方案更简单了,所以如果我可以用他们做我需要的东西,我会这样做; 否则,我使用自定义JsonConverters.但是,我进一步知道两者有时一起使用,因此概念变得更加不透明.

问题:

  1. 是否存在区分何时用户与其他用户的来源?我发现Newtonsoft文档不清楚这两者是如何区分的,或者何时使用其中一种.
  2. 两者之间的排序管道是什么?

json.net

56
推荐指数
1
解决办法
1万
查看次数

如何将参数传递给非默认构造函数?

我有大约以下图片:

public class Foo
{
   public Foo(Bar bar, String x, String y)
   {
       this.Bar = bar;
       this.X = x;
       this.Y = y;
   }

   [JsonIgnore]
   public Bar Bar { get; private set; }

   public String X { get; private set; }
   public String Y { get; private set; }
}

public class Bar
{
    public Bar(String z)
    {
        this.Z = z;
    }

    public String Z { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

我希望以某种方式在反序列化期间将类型为Bar的对象传递给Foo类型的构造函数,即:

var bar = new Bar("Hello world");
var x = …
Run Code Online (Sandbox Code Playgroud)

.net c# json.net

20
推荐指数
2
解决办法
1万
查看次数

无法使用Json.NET对具有多个构造函数的类进行反序列化

我有一个我不用多个构造函数控制的类型,相当于这个:

    public class MyClass
    {
        private readonly string _property;

        private MyClass()
        {
            Console.WriteLine("We don't want this one to be called.");
        }

        public MyClass(string property)
        {
            _property = property;
        }

        public MyClass(object obj) : this(obj.ToString()) {}

        public string Property
        {
            get { return _property; }
        }

    }
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试反序列化它时,将调用私有无参数构造函数,并且永远不会设置该属性.考试:

    [Test]
    public void MyClassSerializes()
    {
        MyClass expected = new MyClass("test");
        string output = JsonConvert.SerializeObject(expected);
        MyClass actual = JsonConvert.DeserializeObject<MyClass>(output);
        Assert.AreEqual(expected.Property, actual.Property);
    }
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

We don't want this one to be called.

  Expected: "test"
  But …
Run Code Online (Sandbox Code Playgroud)

.net c# json json.net

12
推荐指数
1
解决办法
7046
查看次数

Json.NET deserialization of Tuple<...> inside another type doesn't work?

Using Json.net, deserializing a type that contains a Tuple<...> doesn't work (serialization works, but deserialization doesn't):

[TestMethod]
public void Test()
{
    var orig = new TupleHolder("what????", true);
    var json = JsonConvert.SerializeObject(orig);
    Assert.AreEqual("{\"Tup\":{\"Item1\":\"what????\",\"Item2\":true}}", json);
    // great! serialization works like a charm! now let's test deserialization:
    var dupl = JsonConvert.DeserializeObject<TupleHolder>(json);

    Assert.AreEqual("ZZZ", dupl.Tup.Item1); // pass! but it should be "what????"... what????
    Assert.AreEqual(false, dupl.Tup.Item2); // pass! but it should be "true", right???

    Assert.AreEqual(orig.Tup.Item1, dupl.Tup.Item1); // fail!
    Assert.AreEqual(orig.Tup.Item2, dupl.Tup.Item2); // fail!
}

public class TupleHolder …
Run Code Online (Sandbox Code Playgroud)

c# serialization json.net deserialization json-deserialization

7
推荐指数
2
解决办法
5388
查看次数

我可以让 Json.net 使用“主”构造函数反序列化 C# 9 记录类型,就好像它有 [JsonConstructor] 一样?

在 .NET 5.0 上使用 C# 9,我有一堆记录类型,如下所示:

public record SomethingHappenedEvent(Guid Id, object TheThing, string WhatHappened)
{
    public SomethingHappenedEvent(object theThing, string whatHappened)
        : this(Guid.NewGuid(), theThing, whatHappened)
    { }
}
Run Code Online (Sandbox Code Playgroud)

正如您所料,它们被序列化并发送到其他地方进行处理。发送者调用双参数构造函数并获得一个新的 Id,但反序列化器需要使用记录声明隐含的“主要”3 参数构造函数。我正在使用 Newtonsoft Json.NET,我当然希望这能奏效:

        var record = new SomethingHappenedEvent("roof", "caught fire");
        var json = JsonConvert.SerializeObject(record);
        var otherSideRecord = JsonConvert.DeserializeObject<SomethingHappenedEvent>(json);
        Assert.AreEqual(record, otherSideRecord);
Run Code Online (Sandbox Code Playgroud)

当然不是。它抛出 JsonSerializationException。它找不到正确的构造函数,因为有两个,既不是默认的零参数构造函数,也没有标记 JsonConstructorAttribute。我的问题实际上是“我有什么选择来获得类似的东西?”。这会很棒:

[JsonConstructor]
public record SomethingHappenedEvent(Guid Id, object TheThing, string WhatHappened)
{
    public SomethingHappenedEvent(object theThing, string whatHappened)
        : this(Guid.NewGuid(), theThing, whatHappened)
    { }
}
Run Code Online (Sandbox Code Playgroud)

但这会尝试将该属性应用于无效的类型。这是 C# 中的语法错误,但显然它适用于 F#。 …

c# json json.net c#-9.0

7
推荐指数
2
解决办法
2710
查看次数

使用 2 个非默认构造函数反序列化类

我有一个类,它尝试序列化和反序列化给它的对象,使用 Json.net

public class JsonSerializer
{
    public string Serialize(object toSerialaze)
    {
        return JsonConvert.SerializeObject(toSerialaze);
    }

    public T Deserialize<T>(string toDeserialaze)
    {
        return JsonConvert.DeserializeObject<T>(toDeserialaze);
    }
}
Run Code Online (Sandbox Code Playgroud)

并给它一个这样的类的对象

public class Isbn
{
    private readonly int _groupCode;
    private readonly int _publisherCode;
    private readonly int _titleCode;
    private readonly int _checkCode;
    private static readonly Regex Regex = new Regex(@"^\s*\d*\s*-\s*\d*\s*-\s*\d*\s*-\s*\d*\s*$");

    public Isbn(int groupCode, int publisherCode, int titleCode, int checkCode)
    {
        _groupCode = groupCode;
        _publisherCode = publisherCode;
        _titleCode = titleCode;
        _checkCode = checkCode;
    }

    public Isbn(string isbn)
    {
        if …
Run Code Online (Sandbox Code Playgroud)

c# json

6
推荐指数
2
解决办法
1万
查看次数

Json 反序列化受保护的属性

我有一个类属性集,并在构造函数中固定,下面的示例是一个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)

c# json.net

6
推荐指数
1
解决办法
2678
查看次数

C# JSON 反序列化 System.NotSupportedException

我一直在从事一个需要通过 JSON 文件保存和加载数据的项目。此 JSON 文件包含其他对象的各种列表。然而,当我继续反序列化文件时,会发生这种情况:

System.NotSupportedException:不支持不带无参数构造函数、单一参数化构造函数或用“JsonConstructorAttribute”注释的参数化构造函数的类型的反序列化。

负责反序列化的代码如下:

        public void LoadFromJson() {

        int userCount = File.ReadAllLines(folder + "/users").Length;
        int shopCount = File.ReadAllLines(folder + "/shops").Length;
        using (FileStream fileUsers = File.Open(folder + "/users", FileMode.Open, FileAccess.Read)) {
            StreamReader srUser = new StreamReader(fileUsers);
            for(int i=0; i<userCount; i++){
                ListOfUsers.Add(JsonSerializer.Deserialize<User>(srUser.ReadLine()));
            }
            srUser.Close();
            fileUsers.Close();
        }  

        using (FileStream fileShops = File.Open(folder + "/shops", FileMode.Open, FileAccess.Read)){
            StreamReader srShops = new StreamReader(fileShops);
            for(int i=0; i<shopCount; i++){
                ListOfShops.Add(JsonSerializer.Deserialize<Shop>(srShops.ReadLine()));
            }
            srShops.Close();
            fileShops.Close();
        }       

    }
Run Code Online (Sandbox Code Playgroud)

我试图反序列化的类

    public abstract class Shop{

    public List<Sellable> ShopList { …
Run Code Online (Sandbox Code Playgroud)

c# json deserialization system.text.json

4
推荐指数
1
解决办法
3万
查看次数

避免使用默认构造函数和公共属性setter

我正在研究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表示中分离出"真实"对象并在它们之间进行转换,但是我真的很兴奋写一堆样板来做这件事并引入另一层.

有什么我忽略的,或者我只需要咬紧牙关并处理它?

c# json.net signalr

2
推荐指数
1
解决办法
969
查看次数

使用System.Text.Json.Serialization解析json的异常

我的示例代码非常简单:

using System.Text.Json.Serialization;
using Newtonsoft.Json;

public class C {
  public C(string PracticeName) { this.PracticeName = PracticeName; }
  public string PracticeName;
}

var x = new C("1");
var json = JsonConvert.SerializeObject(x); // returns "{\"PracticeName\":\"1\"}"

var x1 = JsonConvert.DeserializeObject<C>(json); // correctly builds a C

var x2 = System.Text.Json.Serialization.JsonSerializer.Parse<C>(json);
Run Code Online (Sandbox Code Playgroud)

最后一行引发:

引发异常:System.Text.Json.dll中的“ System.NullReferenceException”对象引用未设置为对象的实例。

我究竟做错了什么 ?

(Note this is on latest .NET Core 3 preview 5 with latest System.Text.Json 4.6.0-preview6.19259.10)

Adding a parameterless constructor prevents the exception however I don't want/need a parameterless constructor and …

c# json.net .net-core .net-core-3.0 system.text.json

2
推荐指数
1
解决办法
3367
查看次数

反序列化后,Boolean字段始终返回false(Newtonsoft)

我正在使用newtonsoft的json deserialiser,我在包装器中反序列化这个对象:

public class User
{
    public string Username;
    public byte[] HashedPassword;
    public byte[] Salt;
    private bool admin;
    public bool Admin 
    {
        get { return admin; }
    }

    public User(string UsernameArg, byte[] PasswordArg, byte[] SaltArg, bool AdminArg = false)
    {
        Username = UsernameArg;
        HashedPassword = PasswordArg;
        Salt = SaltArg;
        admin = AdminArg;
    }

    public override string ToString()
    {
        return Username;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的json字符串:

{"Users":[{"Username":"admin","HashedPassword":"password","Salt":"salt","Admin":true}]}

(为了便于阅读,我编辑了哈希密码和盐)

因此,每当我使用JsonConvert.DeserializeObject<UserDatabaseClass>(jsonRead)admin字段读取此内容时返回false.

是不是我误解了这里做了什么,还是我做错了?

c# json json.net

1
推荐指数
1
解决办法
1225
查看次数

Newtonsoft json将缺少int值的序列反序列化为空值而不是零

可以这样调整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)

c# json.net

1
推荐指数
1
解决办法
834
查看次数