2

The response output from a JObject content is not well formed in an application.

Narrowing the problem to it's minimum possible size, there should be some missing detail that produce this behavior (very unlikely is other cause).

The following code shows a JSON payload to be the response from an API endpoint:

    [HttpPost]
    public async Task<ObjectResult> Post()
    {
      var json = JsonConvert.DeserializeObject<JObject>(
        @"{""parameter-1"":""J234546ZrVl"",""value-2"":""3E9CY3gertertmdALWMmHkvP"",""test-3"":""verify please""}");
      var result = new ObjectResult(json);

      return result;
    }

The response is received as:

  {"parameter-1":[],"value-2":[],"test-3":[]}

And should be:

  {"parameter-1":"J234546ZrVl","value-2":"3E9CY3gertertmdALWMmHkvP","test-3":"verify please"}

When debugging the variable json is correct, and has all the property values, but somehow it is not rendered correctly.

Any ideas?

  • This is using: ASP Net Core 5.0
  • ObjectResult is defined in: namespace Microsoft.AspNetCore.Mvc
  • Its constructor is: public ObjectResult(object value);
  • And has the interfaces:

public class ObjectResult : ActionResult, IStatusCodeActionResult, IActionResult

dbc
  • 104,963
  • 20
  • 228
  • 340
  • Please give more background - what precise server technologies (including versions) are you using? How have you configured serialization? A [mcve] would be ideal. – Jon Skeet Jun 03 '21 at 09:50
  • Most likely, `ObjectResult` doesn't understand the dynamic handling in `JObject`. – Lasse V. Karlsen Jun 03 '21 at 10:40
  • 1
    Most likely you are using asp.net-core 3.0 or later and which uses System.Text.Json by default instead of Json.NET. Your symptoms are similar to the ones from [How can I serialize a Newtonsoft JToken to JSON using System.Text.Json?](https://stackoverflow.com/q/65386083/3744182). To switch back to Json.NET see [Where did IMvcBuilder AddJsonOptions go in .Net Core 3.0?](https://stackoverflow.com/q/55666826/3744182). If that is not the problem please provide more details about how to reproduce the problem including the framework and library versions you are using. – dbc Jun 03 '21 at 11:55
  • what is the content of ObjectResult? why do you need it? you can return the "json" or DeserializeObject directly to "ObjectResult". please add the "ObjectResult" class to the question. – Yair I Jun 03 '21 at 13:42
  • The reason to use "ObjectResult" is the capability to handle the returned payload and the HTTP status code response in same variable across methods. – TrustworthySystems Jun 03 '21 at 14:39
  • 2
    If you are using asp.net-core-5 easiest would be to replace `JObject` with [`JsonElement`](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonelement?view=net-5.0), i.e. `var json = System.Text.Json.JsonSerializer.Deserialize(jsonString);`. See: [Equivalent of JObject in System.Text.Json](https://stackoverflow.com/q/65620060/3744182). – dbc Jun 03 '21 at 20:05
  • Can your question be closed off as a duplicate of any of the questions linked to above, or do you need more specific help? Or did none of the linked questions resolve your problem after all? – dbc Jun 04 '21 at 13:37

2 Answers2

2

Thanks to dbc tips, we can use the legacy services, just serializing its return value with the previous Newtonsoft.Json library and deserializing with the new System.Text.Json.

This method can do the trick and can be used across the whole application, probably for really big JSON values is not the optimum, but is clean and lean for our requirements.

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text.Json;

...

  public static JsonDocument JToken2JsonDocument(JToken input)
  {
    var jsonString = JsonConvert.SerializeObject(input);
    var json = JsonDocument.Parse(jsonString);
    return json;
  }

The ObjectResult constructor can be called with the returned object and render correctly.

  • 1
    [`JsonDocument`](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsondocument?view=net-5.0#remarks)* implements `IDisposable`. *Failure to properly dispose this object will result in the memory not being returned to the pool, which will increase GC impact across various parts of the framework.* Better to clone the [`RootElement`](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsondocument.rootelement), dispose the document, and return the clone. – dbc Jun 06 '21 at 14:22
0

In my case, I had to replace to Newtonsoft.Json.

source: https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting

Relevant parts extracted from the link:

"To use the Newtonsoft.Json-based formatters, install the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package and configure it in Program.cs:"

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers()
        .AddNewtonsoftJson();

And change all my code to use JsonConvert.DeserializeObject().

Cesar
  • 420
  • 6
  • 12