7

My sample code is very simple:

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

the last line raises:

Exception thrown: 'System.NullReferenceException' in System.Text.Json.dll Object reference not set to an instance of an object.

What am I doing wrong ?

(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 Json.Net parses fine without it.

Is there a way to make System.Text.Json parse using the given constructor like Json.Net does ?

dbc
  • 104,963
  • 20
  • 228
  • 340
kofifus
  • 17,260
  • 17
  • 99
  • 173
  • 4
    Have you tried to add parameterless constructor? – Szymon Tomczyk Jun 07 '19 at 00:31
  • 1
    ok, adding a parameterless constructor prevents the exception however I don't want/need a parameterless constructor and json.net parses fine without it – kofifus Jun 07 '19 at 00:52
  • I think, in general, a parameter-less constructor has always been a prerequisite in serializable types. thinking of .NET scenarios that I am familiar with. XML Serialization, etc. – Glenn Ferrie Jun 07 '19 at 00:59
  • 1
    see in my sample - Json.NET has no problem without a parameterless constructor , also I can't find any docs that it is needed – kofifus Jun 07 '19 at 01:03
  • @kofifus have you checked this [QA](https://stackoverflow.com/a/23017892/4648586) previously? – Bagus Tesa Jun 07 '19 at 01:07
  • 1
    @BagusTesa, again as seen above, Json.Net has no problem with desalinizing my object, and since there is a single constructor there is no need for the [JsonConstructor] attribute – kofifus Jun 07 '19 at 01:10
  • Json.net assumes a constructor parameter to be a property, if the name is equal (except common naming convention). That said, Json support in [.net core](https://github.com/dotnet/corefx/issues/33115) is still an open issue. Consider posting there. – Christian Gollhardt Jun 07 '19 at 01:26
  • As of **.NET 5** deserialization of types with parameterized constructors using `System.Text.Json` now works, see [Deserialize anonymous type with System.Text.Json](https://stackoverflow.com/q/59313256/3744182). – dbc Mar 06 '21 at 18:30

3 Answers3

18

In it's current state, JSON Support in .NET Core 3.0 is still not finished, and it seems only a parameterless constructor is supported. It might be, that that feature will be added in future.

One workaround option would be to make a parameterless constructor for your serialized model, when you want to use the new Json API from the .net framework. Probably we shouldn't use constructors for plain datatransfer objects at all, hence I see it as option, not as a workaround.

If you search for a way, on how to migrate from an older version to .net core 3.0, or use Newtonsoft.Json anyway, this is documented here:

MVC:

Install Microsoft.AspNetCore.Mvc.NewtonsoftJson package, and register it to your services:

services.AddMvc().AddNewtonsoftJson();

SignalR:

Install Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson package

//Client
new HubConnectionBuilder()
.WithUrl("/chatHub")
.AddNewtonsoftJsonProtocol(...)
.Build();

//Server
services.AddSignalR().AddNewtonsoftJsonProtocol(...);

That way you should* be able to use Json.NET Features in .Net Core 3.0

*I don't have installed it, so I can not test it

Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
  • For me `AddNewtonsoftJson` method doesn't exit. – Saeed Neamati Oct 22 '19 at 10:06
  • 1
    Did you installed above nuget package and imported the namespace [`Microsoft.Extensions.DependencyInjection`](https://github.com/aspnet/AspNetCore/blob/1189a2c294df55d7a67f1bc6ea74d74858f467bd/src/Mvc/Mvc.NewtonsoftJson/src/DependencyInjection/NewtonsoftJsonMvcBuilderExtensions.cs#L19)? Also notice it is an method on `IMvcBuilder` and not `IServiceCollection`. You need to use it with `AddMvc` as shown above @SaeedNeamati – Christian Gollhardt Oct 22 '19 at 15:04
2

PracticeName needs to be a property, not a field. Try that w/ the parameterless constructor.

I developed a quick console program class. The class C1 is converted via the Newtonsoft.Json package. The class C2 is parsed via the System.Text.Json package.

using Newtonsoft.Json;

namespace TestJsonParse
{
    class Program
    {
        static void Main(string[] args)
        {
            var c1 = new C1("1");
            var json1 = JsonConvert.SerializeObject(c1); // returns "{\"PracticeName\":\"1\"}"
            var x1 = JsonConvert.DeserializeObject<C1>(json1); // correctly builds a C1

            var c2 = new C2();
            string json2 = "{\"PracticeName\":\"1\"}";
            var x2 = System.Text.Json.Serialization.JsonSerializer.Parse<C2>(json2); // correctly builds a C2
        }

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

        class C2
        {
            public C2() { }
            public string PracticeName { get; set; }
        }
    }
}
  • Perhaps you could post a code sample illustrating your suggested solution? – Abra Jun 07 '19 at 01:08
  • Thanks, are you saying I can't serialize fields ? also I don't want an empty ctor, my real case involves a whole lot of classes many of them without an empty ctor, and Json.NET has no problem with that. – kofifus Jun 07 '19 at 01:13
  • @kofifus With System.Text.Json, that seems to be the case (at least as far as the Parse method is concerned). –  Jun 07 '19 at 01:32
  • Did you read my edit comment? Please do not write the word *edit*. It's just noise. We already see this in the edit history ;) – Christian Gollhardt Jun 07 '19 at 01:32
  • @ChristianGollhardt Sorry about that. Still learning the etiquette. –  Jun 07 '19 at 01:35
  • So you're saying that System.Text.Json requires a parameterless constructor whereas Json.NET does not ? do you have a reference for that ? thx! – kofifus Jun 07 '19 at 01:49
0

Json Support with System.Text.Json.Serialization is quite unstable. It is better to use NewtonSoft.Json as it is more stable and almost everyone uses that. If running a console app then from the folder in your terminal do enter image description here

You are not required to specify the version though. If using visual studio then use Nuget package manager to install Newtonsoft.json.

To read json from a file for example data.json

{
  "Name":"Logan",
  "Age": 30
  "Books": ["Infinity War", "End Game"]
}

Specify your properties example

class Person
{
  public string Name{get; set;}
  public int Age{get; set;}
  public IList<string> Books{get; set;}
}

then from the class you wish to access the json data do the following

string fileContent = System.IO.File.ReadAllText(@"./data.json");
Person person = Newtonsoft.Json.JsonConverter.DeserializeObject<Person>(fileContent);

test it

Console.WriteLine($"Hi {person.Name} you are {person.Age} today read {person.Books[0]}");

For more info go to https://www.newtonsoft.com/json/help/html/DeserializeObject.htm

N Djel Okoye
  • 950
  • 12
  • 10