Home > other >  JSON Self referencing loop on POST call
JSON Self referencing loop on POST call

Time:03-17

I'm trying to send a POST call via JsonApi with this as example:

{
    "data": {
        "attributes": {
            "booked_by_patient": true,
            "class": "PUBLIC",
            "description": "description",
            "dtend": "2022-03-16T10:30:00 01:00",
            "dtstamp": "2022-03-16T10:01:17 01:00",
            "dtstart": "2022-03-16T10:00:00 01:00",
            "location": "1231, 31311 3131",
            "new_patient": true,
            "referral_source": "",
            "status": "CONFIRMED",
            "summary": "summary",
            "text": "",
            "transp": "OPAQUE",
            "uid": null,
            "first_name": "name",
            "last_name": "last_name",
            "e_mail_address": "[email protected]",
            "phone_number_cell": " 467325324563252"
        },
        "relationships": {
            "clinic": {
                "data": {
                    "id": "2312",
                    "type": "Pizza-clinics"
                }
            },
            "organizer": {
                "data": {
                    "id": "5553",
                    "type": "Pizza-caregivers"
                }
            },
            "procedure": {
                "data": {
                    "id": "1",
                    "type": "Pizza-procedure"
                }
            }
        },
        "type": "Pizza-bookings"
    },
    "include": "booking_attendees.patient"
}

But for starters, I'm getting an error for "Self referencing loop detected for property 'data' with type 'SDKs.Pizza.Model.Clinics'. Path 'data.clinic.data'.

following another suggestion I received that I needed to add a [JsonIgnore] decorator over some models, I have done the following: (decorator over 3 last objects)

public class BookingRequest 
    {
        // public string Id { get; set; }
        public string? Uid { get; set; } = null;

        public string Type { get; } = "pizza_bookings";

        public bool BookedByPatient { get; set; } = true;

        public string Class { get; set; } = "PUBLIC";

        public string Description { get; set; } = null!;
        
        [JsonProperty(PropertyName = "dtstart")]
        public DateTimeOffset Start { get; set; }
        
        [JsonProperty(PropertyName = "dtend")]
        public DateTimeOffset End { get; set; }
        
        [JsonProperty(PropertyName = "dtstamp")]
        public DateTimeOffset Timestamp { get; set; } = DateTimeOffset.UtcNow;

        public string EMailAddress { get; set; } = null!;

        public string FirstName { get; set; } = null!;

        public string LastName { get; set; } = null!;

        public string Location { get; set; } = null!;

        public bool NewPatient { get; set; } = true;

        public string PhoneNumberCell { get; set; } = null!;

        public string ReferralSource { get; set; } = "source";

        public string Status { get; set; } = "CONFIRMED";

        public string Summary { get; set; } = "";

        public string Text { get; set; } = "";

        public string? Transp { get; set; } = "OPAQUE";

        [JsonIgnore]
        public Relationship<Clinics> Clinic { get; set; } = null!;
        [JsonIgnore]
        public Relationship<Caregivers> Organizer { get; set; } = null!;
        [JsonIgnore]
        public Relationship<Procedures> Procedure { get; set; } = null!;
    }

My current POST call is as follows:

public async Task<Booking?> CreateBookingAsync(string clinicId, string caregiverId, string procedureId, string ssn,
            DateTimeOffset start, DateTimeOffset end)
        {
            var uri = "api/pizza-bookings".AddQueryParams(new Dictionary<string, string?> {
                                                ["caregiver_id"] = caregiverId,
                                                ["patient_personal_id"] = swedishPersonalIdentityNumber
                                            }
            );

            var body = new DocumentRoot<BookingRequest>();

            var clinic = new Relationship<Clinics>() {Data = new Clinics() {Id = clinicId}};

            var organizer = new Relationship<Caregivers>() {Data = new Caregivers() {Id = caregiverId}};

            var procedure = new Relationship<Procedures>() {Data = new Procedures() {Id = procedureId}};

            body.Data = new BookingRequest() {
                Start = start,
                End = end,
                EMailAddress = "[email protected]",
                PhoneNumberCell = "123-456-789",
                FirstName = "first-name",
                LastName = "last-name",
                Clinic = clinic,
                Organizer = organizer,
                Procedure = procedure
            };

            return await _http.SendInternalAsync<DocumentRoot<BookingRequest>, Booking>(HttpMethod.Post, uri, body, new Dictionary<string, string>());
            }

the issue that I have here is that if I add the jsonIgnore the code runs, but the JSON I capture from Fiddler is the following:

{
    "data": {
        "type": "pizza_bookings",
        "bookedByPatient": true,
        "class": "PUBLIC",
        "dtstart": "2022-03-17T08:56:00 01:00",
        "dtend": "2022-03-17T09:26:00 01:00",
        "dtstamp": "2022-03-17T07:56:48.3039336 00:00",
        "eMailAddress": "[email protected]",
        "firstName": "first-name",
        "lastName": "last-name",
        "newPatient": true,
        "phoneNumberCell": "123-456-789",
        "referralSource": "source",
        "status": "CONFIRMED",
        "summary": "",
        "text": "",
        "transp": "OPAQUE",
        "clinic": {
            "data": {}
        },
        "organizer": {
            "data": {}
        },
        "procedure": {
            "data": {}
        }
    }
}

CodePudding user response:

You can ignore the self-referencing loops while serializing by using ReferenceLoopHandling.Ignore which will not serialize an object if it is a child object of itself. You can use it by adding it in your serializer settings:

JsonConvert.SerializeObject(body.Data, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore});

CodePudding user response:

The Decorators is a good starting point, but you need to use a structure a little diferent:

public class Attributes
{
    [JsonProperty("booked_by_patient")]
    public bool BookedByPatient { get; set; }

    [JsonProperty("class")]
    public string Class { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("dtend")]
    public DateTime Dtend { get; set; }

    [JsonProperty("dtstamp")]
    public DateTime Dtstamp { get; set; }

    [JsonProperty("dtstart")]
    public DateTime Dtstart { get; set; }

    [JsonProperty("location")]
    public string Location { get; set; }

    [JsonProperty("new_patient")]
    public bool NewPatient { get; set; }

    [JsonProperty("referral_source")]
    public string ReferralSource { get; set; }

    [JsonProperty("status")]
    public string Status { get; set; }

    [JsonProperty("summary")]
    public string Summary { get; set; }

    [JsonProperty("text")]
    public string Text { get; set; }

    [JsonProperty("transp")]
    public string Transp { get; set; }

    [JsonProperty("uid")]
    public object Uid { get; set; }

    [JsonProperty("first_name")]
    public string FirstName { get; set; }

    [JsonProperty("last_name")]
    public string LastName { get; set; }

    [JsonProperty("e_mail_address")]
    public string EMailAddress { get; set; }

    [JsonProperty("phone_number_cell")]
    public string PhoneNumberCell { get; set; }
}

public class Data
{

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("attributes")]
    public Attributes Attributes { get; set; }

    [JsonProperty("relationships")]
    public Relationships Relationships { get; set; }
}

public class Data2
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }
}

public class Clinic
{
    [JsonProperty("data")]
    public Data2 Data { get; set; }
}

public class Organizer
{
    [JsonProperty("data")]
    public Data2 Data { get; set; }
}

public class Procedure
{
    [JsonProperty("data")]
    public Data2 Data { get; set; }
}

public class Relationships
{
    [JsonProperty("clinic")]
    public Clinic Clinic { get; set; }

    [JsonProperty("organizer")]
    public Organizer Organizer { get; set; }

    [JsonProperty("procedure")]
    public Procedure Procedure { get; set; }
}

public class Root
{
    [JsonProperty("data")]
    public Data Data { get; set; }

    [JsonProperty("include")]
    public string Include { get; set; }
}

you can check a deserialize /serialize working example here

https://dotnetfiddle.net/Vn8JrU

  • Related