简体   繁体   中英

How to serialize JSON in C# without child

I created a controller for returning JSON to a mobile application. Given this action:

public JsonResult GetFirm(int id)
{
    Firm firm = new Firm();
    firm = dbContext.Firms.FirstOrDefault(s => s.id == id);
    string firmString = JsonConvert.SerializeObject(firm);
    return Json(firmString, JsonRequestBehavior.AllowGet);
}

This method(above method) throw self referencing loop error and I write :

Firm firm = new Firm();
firm = dbContext.Firms.FirstOrDefault(s => s.id == id);
string firmString = JsonConvert.SerializeObject(firm, Formatting.None,
    new JsonSerializerSettings()
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    });
return Json(firmString, JsonRequestBehavior.AllowGet);

But this method send object with all child and collections and json include "\\" before all attribute.

I want to send json object without child or collections.

Analysis and Issue

Your issue is clearly somewhere in your model you have a circular reference. I am highly confident it is due to you are trying to deserialize a database model (an EF model at a guess) directly. Doing that is not recommended.

A database model will contain references typically to other classes, which in themselves reference back to the first class due to representing a database structure. So you likely have something like:

public class ParentItemDataModel
{
    [Key]
    public Guid Id { get; set; }

    public string SomeInfo { get; set; }

    public List<ChildItemDataModel> Children { get; set; }
}

public class ChildItemDataModel
{
    public ParentItemDataModel Parent { get; set; }

    public string SomeInfo { get; set; }
}

So as you can see, a clear reference loop if deserialized.

Recommendation

Separate your API models returned to clients from your underlying database models by creating a new, simple class that contains only the required information such as:

public class ParentItemApiModel
{
    public Guid Id { get; set; }

    public string SomeInfo { get; set; }
}

Then you can get that information into the model the old-fashioned way:

var parentApiModel = new ParentItemApiModel
{
    Id = dataModel.Id,
    SomeInfo = dataModel.SomeInfo
};

Or you can do it with an extension method in your data model (so your typically lower core Api model has no reference back up to the database layer):

public static class DataModelExtensions
{
    public static ParentItemApiModel ToApiModel(this ParentItemDataModel dataModel)
    {
        return new ParentItemApiModel
        {
            Id = dataModel.Id,
            SomeInfo = dataModel.SomeInfo
        };
    }
}

So that now you can do this:

var apiModel = dataModel.ToApiModel();

Or in your example that would then be:

string firmString = JsonConvert.SerializeObject(firm.ToApiModel());

Or any other way you like.

Direct fix

If you do not want to fix it by the recommendation, the quickest, simplest way is to flag your data model Firm properties that you don't want in the JSON model with [JsonIgnore] .

Try returing a string instead of JsonResult

public string GetFirm(int id)
{

    Firm firm = new Firm();
    firm = dbContext.Firms.FirstOrDefault(s => s.id == id);
    string firmString = JsonConvert.SerializeObject(firm, Formatting.None,
                new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                });
    return firmString;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM