3

My endpoint sends an object which contains JSON strings such as:

{
    "id": 42,
    "sender": "{\"id\": 3, \"name\": \"John\"}"
}

How do I get the serializer to parse JSON strings to JSON objects before sending it to the client?
I have this config:

services.AddControllers().AddNewtonsoftJson(builder =>
{
    builder.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
    builder.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});

Edit

This post has been flagged duplicate of this question. Please note that I'm looking for a global way to ensure it, that would be set during ConfigureServices of Startup.cs. Thanks.

That is to say (to be even more understandable):

  • Has to be a one-time configuration set (I'm aware of custom JsonConverter, but you have to pass a new instance of it for each serialization)
  • Note also that I can't call DeserializeObject<> or SerializeObject, the ASP framework handles serialization.

Here is a piece of code which returns a JSON string I'd like to be auto-escaped during the framework serialization:

[EnsureUserHasPrivilegeActionFilter(Privilege.CanManageLostObjects)]
[HttpGet]
public IEnumerable<CityLostObject> GetLostObjects ()
{
    var objects = DbContext.CityLostObject.Where(l => l.CityId == RequestedCity.Id);
    
    foreach (var lostObject in objects)
    {
        lostObject.City = null;
    }
   
    return objects;
}

This endpoint returns a JSON structure like so:

[
  {
    "$id": "59",
    "id": 3,
    "description": "string type",
    "location": "string type",
    "sender": "{\"Email\": \"string email\", \"Phone\": \"0621232145\", \"LastName\": \"last name\", \"FirstName\": \"first name\"}",
    "tags": [
      "found"
    ],
    "cityId": 5,
    "date": "2020-09-03T00:00:00"
  }
]

Here I'd like sender to be escaped. And as a general rule, every JSON-like strings to be so.

Here is the C# class:

public partial class CityLostObject
{
    public int Id { get; set; }
    public string Description { get; set; }
    public string Location { get; set; }
    public string PictureUrl { get; set; }
    public string Sender { get; set; }
    public string[] Tags { get; set; }
    public int CityId { get; set; }
    public DateTime Date { get; set; }
    public virtual City City { get; set; }
}

And the partial overload which converts the JSON string to object:

public partial class CityLostObject
{
    [NotMapped]
    public SenderData SenderParsed
    {
        get => JsonConvert.DeserializeObject<SenderData>(Sender);
        set => Sender = JsonConvert.SerializeObject(value);
    }
    
    public class SenderData
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
    }
}

Why not parse JSON string on client-side?

  • That is not the role of the client to "fix" the API's response.
  • The API should send valid data.
  • The client should not modify API data, but interpret it.
  • It brings code complexity and maintenance costs to do that for every endpoint.
Alexandre Daubricourt
  • 3,323
  • 1
  • 34
  • 33
  • 3
    Can you please add code for action which has this output? Add model class if any. – Guru Stron Sep 03 '20 at 13:05
  • 3
    You can return the same json string and parse it to JSON object on the client side, will that not work for you? – Sowmyadhar Gourishetty Sep 03 '20 at 13:09
  • As this question has been kindly closed, I had to make a repost here: https://stackoverflow.com/questions/63744488/asp-net-core-web-api-parse-json-string-properties :) – Alexandre Daubricourt Sep 04 '20 at 16:00
  • I have added an additional duplicate, [Customizing response serialization in ASP.NET Core MVC](https://stackoverflow.com/questions/49179047/customizing-response-serialization-in-asp-net-core-mvc/49189185), which answers a part of your question, _"I'm looking for a global way to ensure it, that would be set during ConfigureServices"_. So: write that custom converter, and register it where required. Once, globally. – CodeCaster Sep 04 '20 at 16:13
  • @SowmyadharGourishetty Parsing it on the client side would work but it my case that'd be a bad pattern because it is not the role of the client to modify the API result, and I don't want to do it each time for other objects, thus It'd add complexity and maintenance costs – Alexandre Daubricourt Sep 10 '20 at 13:06

0 Answers0