JSON POST 调用时的自引用循环

JSON Self referencing loop on POST call

我正在尝试通过 JsonApi 发送 POST 调用,例如:

{
    "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@domain.com",
            "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"
}

但是对于初学者来说,我收到一个错误“检测到类型为 'SDKs.Pizza.Model.Clinics' 的 属性 'data' 的自引用循环。路径 'data.clinic.data'.

根据我收到的另一个建议,我需要在某些模型上添加 [JsonIgnore] 装饰器,我做了以下操作:(装饰器在最后 3 个对象上)

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!;
    }

我目前的POST调用如下:

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@domain.com",
                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>());
            }

我在这里遇到的问题是,如果我添加 jsonIgnore,代码会运行,但是 JSON 我从 Fiddler 捕获的内容如下:

{
    "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@domain.com",
        "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": {}
        }
    }
}

您可以在使用 ReferenceLoopHandling.Ignore 序列化时忽略 self-referencing 循环,如果对象是其自身的子对象,则不会序列化该对象。您可以通过在序列化程序设置中添加它来使用它:

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