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.
5
  • 3
    Can you please add code for action which has this output? Add model class if any. Commented Sep 3, 2020 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? Commented Sep 3, 2020 at 13:09
  • As this question has been kindly closed, I had to make a repost here: stackoverflow.com/questions/63744488/… :) Commented Sep 4, 2020 at 16:00
  • I have added an additional duplicate, Customizing response serialization in ASP.NET Core MVC, 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. Commented Sep 4, 2020 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 Commented Sep 10, 2020 at 13:06

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.