0

I'm making a Web Service in C# and I decided to use Newtonsoft.Json to handle my Json related tasks. However, I'm having a problem for some time. I made a minimal working example of the issue I'm currently having. I'm using .NET 7.0.

I have the following class that I will return as a IActionResult.

public record class Test
{
    [JsonProperty]
    public JArray Array { get; set; }

    [JsonConstructor]
    public Test() {
        Array = new JArray();
    }
}

This is what my code currently does:

[HttpGet("{test}")]
public IActionResult Test(string test)
{
    Test a = new();

    JObject b = new JObject();

    b.Add("foo", "bar");
            
    a.Array.Add(b);

    return Ok(a);
}

And this is what I get in the Response Body:

{
    "array": [
        [
            [
                []
            ]
        ]
    ]
}

What I expected to get was something like:

{
    "array": [
        {
            "foo" : "bar"
        }
    ]
}

I managed to narrow down the issue to either being in the JArray or the JObject, if I try to return the JObject directly I get something like this:

{
    "foo" : []
}

So I'm guessing It's failing to access the value of the property? What is weird about this is that if I do a JsonConvert.Serialize and pass it either the JObject or the Test object, every value appears in the string, it's when I try to return the Objects that it fails to show the values.

I tried reading the Newtonsoft documentation on the types JObject and JArray but I seem to be doing what is the required to get the correct result, I have the getters and setters, I have the Json attributes, and there really isn't a whole lot of information on this particular issue I'm encountering.

dryfish
  • 9
  • 3
  • Why do you use a JArray to begin with? JArray is for parsing or for building objects, not for serializing. Use a typed array such as `string[]`, or `dynamic` if you don't know what you want to put in there (but don't, actually). – CodeCaster Apr 13 '23 at 15:23
  • The code is manually building the Json, that is the reason why it's currently using JObject and JArray. – dryfish Apr 13 '23 at 15:27
  • 1
    Do you register Newtonsoft with MVC? – CodeCaster Apr 13 '23 at 15:30
  • 1
    Is the web-server even using Newtonsoft? that isn't the default now, in which case: that could be the confusion – Marc Gravell Apr 13 '23 at 15:34
  • But you really shouldn't be building responses using JArray. That throws all type safety overboard. Code can put anything in it it likes. You can't document (OpenAPI) what your callers can expect. – CodeCaster Apr 13 '23 at 15:41
  • @MarcGravell yes, I installed the package thru NuGet Package Manager. – dryfish Apr 13 '23 at 15:51
  • @CodeCaster the code I'm working on was made this way using .NET 3.0. I'm updating the .NET version to .NET 7.0, and I'm getting this issue. – dryfish Apr 13 '23 at 15:53
  • 1
    That is because MVC changed from Newtonsoft to System.Text.Json. In your startup, at .AddMvc(), you need to tell it you're using Newtonsoft. See duplicate: https://stackoverflow.com/questions/42290811/how-to-use-newtonsoft-json-as-default-in-asp-net-core-web-api – CodeCaster Apr 13 '23 at 15:54
  • @CodeCaster I will try your suggestion. – dryfish Apr 13 '23 at 16:00
  • I'm quite certain that should fix it, if not, let me know and I'll reopen in no time. – CodeCaster Apr 13 '23 at 16:00
  • Either enable using Newtonsoft Json.NET in ASP.NET Core or use similar `JsonNode` API from System.Text.Json. – Guru Stron Apr 13 '23 at 16:01
  • @CodeCaster your suggestion worked. Thanks a bunch! Is there anything I should do on my side regarding this post? – dryfish Apr 13 '23 at 16:02
  • Good to hear! No it's okay, it will point others who search using your terms towards the duplicate containing the answers! – CodeCaster Apr 13 '23 at 16:03

1 Answers1

-1

Your code is working Ok for me, but you must be using Text.Json in your controller actions, but if you try to create a json string manually try anonymous class

    var a = new { Array = new[] { new { foo = "bar" } }};

or if you want to use Newtonsoft.Json every where ( and I highly recommend you ) add this to your Program (Startup) file

builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
  options.SerializerSettings.ContractResolver =
        new CamelCasePropertyNamesContractResolver());
Serge
  • 40,935
  • 4
  • 18
  • 45