private static List <ListDataAsStreamProperty> TransformRowData(JsonElement row, IFieldCollection fields, Dictionary <string, IField> fieldLookupCache) { List <ListDataAsStreamProperty> properties = new List <ListDataAsStreamProperty>(); foreach (var property in row.EnumerateObject()) { // Doing the field lookup is expensive given it happens per field/row, caching drastically improves performance when reading large sets of items if (!fieldLookupCache.TryGetValue(property.Name, out IField field)) { field = fields.AsRequested().FirstOrDefault(p => p.InternalName == property.Name); fieldLookupCache.Add(property.Name, field); } if (field != null) { var streamProperty = new ListDataAsStreamProperty() { Field = field, Type = field.FieldTypeKind, Name = property.Name }; // Is this a field that needs to be wrapped into a special field type? var specialField = DetectSpecialFieldType(streamProperty.Name, field); if (specialField != null) { streamProperty.IsArray = specialField.Item2; if (property.Value.ValueKind == JsonValueKind.Array) { #region Sample json responses /* * "PersonSingle": [ * { * "id": "15", * "title": "Kevin Cook", * "email": "*****@*****.**", * "sip": "*****@*****.**", * "picture": "" * } * ], * * "PersonMultiple": [ * { * "id": "14", * "value": "Anna Lidman", * "title": "Anna Lidman", * "email": "*****@*****.**", * "sip": "*****@*****.**", * "picture": "" * }, * { * "id": "6", * "value": "Bert Jansen (Cloud)", * "title": "Bert Jansen (Cloud)", * "email": "*****@*****.**", * "sip": "*****@*****.**", * "picture": "" * } * ], * * "MMSingle": { * "__type": "TaxonomyFieldValue:#Microsoft.SharePoint.Taxonomy", * "Label": "LBI", * "TermID": "ed5449ec-4a4f-4102-8f07-5a207c438571" * }, * * "MMMultiple": [ * { * "Label": "LBI", * "TermID": "ed5449ec-4a4f-4102-8f07-5a207c438571" * }, * { * "Label": "MBI", * "TermID": "1824510b-00e1-40ac-8294-528b1c9421e0" * }, * { * "Label": "HBI", * "TermID": "0b709a34-a74e-4d07-b493-48041424a917" * } * ], * * "LookupSingle": [ * { * "lookupId": 71, * "lookupValue": "Sample Document 01", * "isSecretFieldValue": false * } * ], * * "LookupMultiple": [ * { * "lookupId": 1, * "lookupValue": "General", * "isSecretFieldValue": false * }, * { * "lookupId": 71, * "lookupValue": "Sample Document 01", * "isSecretFieldValue": false * } * ], * * "Location": { * "DisplayName": null, * "LocationUri": "https://www.bingapis.com/api/v6/addresses/QWRkcmVzcy83MDA5ODMwODI3MTUyMzc1ODA5JTdjMT9h%3d%3d?setLang=en", * "EntityType": null, * "Address": { * "Street": "Somewhere", * "City": "XYZ", * "State": "Vlaanderen", * "CountryOrRegion": "Belgium", * "PostalCode": "9999" * }, * "Coordinates": { * "Latitude": null, * "Longitude": null * } * }, */ #endregion // Add values that will become part of a FieldValueCollection later on foreach (var streamPropertyElement in property.Value.EnumerateArray()) { (var fieldValue, var isArray) = DetectSpecialFieldType(streamProperty.Name, field); var listDataAsStreamPropertyValue = new ListDataAsStreamPropertyValue() { FieldValue = fieldValue }; foreach (var streamPropertyElementValue in streamPropertyElement.EnumerateObject()) { listDataAsStreamPropertyValue.Properties.Add(streamPropertyElementValue.Name, GetJsonPropertyValueAsString(streamPropertyElementValue.Value)); } streamProperty.Values.Add(listDataAsStreamPropertyValue); } } else { /* * "Url": "https:\u002f\u002fpnp.com\u002f3", * "Url.desc": "something3", * * "LookupSingleField1": "", * "LookupSingleField1.": "", */ var listDataAsStreamPropertyValue = new ListDataAsStreamPropertyValue() { FieldValue = specialField.Item1 }; if (property.Value.ValueKind == JsonValueKind.Object) { foreach (var streamPropertyElementValue in property.Value.EnumerateObject()) { if (streamPropertyElementValue.Value.ValueKind == JsonValueKind.Object) { foreach (var streamPropertyElementValueLevel2 in streamPropertyElementValue.Value.EnumerateObject()) { listDataAsStreamPropertyValue.Properties.Add(streamPropertyElementValueLevel2.Name, GetJsonPropertyValueAsString(streamPropertyElementValueLevel2.Value)); } } else { listDataAsStreamPropertyValue.Properties.Add(streamPropertyElementValue.Name, GetJsonPropertyValueAsString(streamPropertyElementValue.Value)); } } } else { listDataAsStreamPropertyValue.Properties.Add(property.Name, GetJsonPropertyValueAsString(property.Value)); } streamProperty.Values.Add(listDataAsStreamPropertyValue); } } else { // Add as single property or simple choice collection /* * "Title": "Item1", * * "ChoiceMultiple": [ * "Choice 1", * "Choice 3", * "Choice 4" * ], */ streamProperty.Value = property.Value; } properties.Add(streamProperty); } else { /* * "Url.desc": "something3", * "DateTime1.": "2020-12-04T11:15:15Z", */ if (property.Name.Contains(".")) { string[] nameParts = property.Name.Split(new char[] { '.' }); var propertyToUpdate = properties.FirstOrDefault(p => p.Name == nameParts[0]); if (propertyToUpdate != null && propertyToUpdate.Values.Count == 1 && !string.IsNullOrEmpty(nameParts[1])) { var valueToUpdate = propertyToUpdate.Values.FirstOrDefault(); if (valueToUpdate == null) { valueToUpdate = new ListDataAsStreamPropertyValue(); propertyToUpdate.Values.Add(valueToUpdate); } if (!valueToUpdate.Properties.ContainsKey(nameParts[1])) { valueToUpdate.Properties.Add(nameParts[1], GetJsonPropertyValueAsString(property.Value)); } } else if (propertyToUpdate != null && !string.IsNullOrEmpty(nameParts[1])) { //"Bool1.value": "1", if (!fieldLookupCache.TryGetValue(nameParts[0], out IField field2)) { field2 = fields.AsRequested().FirstOrDefault(p => p.InternalName == nameParts[0]); fieldLookupCache.Add(nameParts[0], field2); } // Extra properties on "regular" fields if (field2 != null && field2.FieldTypeKind == FieldType.Boolean && nameParts[1] == "value") { propertyToUpdate.Value = property.Value; } } else if (propertyToUpdate != null && string.IsNullOrEmpty(nameParts[1])) { // override the set Value propertyToUpdate.Value = property.Value; } } } } return(properties); }