У меня есть сторонний веб-API, который возвращает ответ json, содержащий escape-символы и множество обратных косых черт, как показано ниже.
Моя цель - прочитать всю группу услуг и связанные с ней услуги. Я не могу этого сделать даже после использования replace, regex.
{
"name": "servicesGroups",
"value": "[{\"id\":\"ServiceGroup1\",\"types\":[\"books\"],\"services\":[{\"id\":2,\"calendarId\":2,\"publicId\":\"1234567890\"},{\"id\":1,\"calendarId\":1,\"publicId\":\"0987654321\"}],\"names\":{\"en\":\"Service Group1\"}},{\"id\":\"ServiceGroup2\",\"types\":[\"books\"],\"services\":[{\"id\":2,\"calendarId\":2,\"publicId\":\"7575637576457457567\"},{\"id\":1,\"calendarId\":1,\"publicId\":\"2143658709\"}],\"names\":{\"en\":\"ServiceGroup2\"}]"
}
Вот как я вижу через отладку:
RootObject root = JsonConvert.DeserializeObject<RootObject>(servicegroupsjson);
List<ServicesGroup> servicesGroups = JsonConvert.DeserializeObject<List<ServicesGroup>>(root.value); - Compile time error
public class Service
{
public int id { get; set; }
public int calendarId { get; set; }
public string publicId { get; set; }
}
public class Names
{
public string en { get; set; }
}
public class ServicesGroup
{
public string id { get; set; }
public List<string> types { get; set; }
public List<Service> services { get; set; }
public Names names { get; set; }
}
public class RootObject
{
public string name { get; set; }
public List<ServicesGroup> value { get; set; }
}
На самом деле, кажется, что-то не так с json, и в конце его слишком много }. В \"names\":{\"en\":\"ServiceGroup2\"}}}]" у вас, конечно, есть один, чтобы закрыть имена, другой, чтобы закрыть Службу, но тогда у вас должен быть ], чтобы закрыть список. Вместо этого есть } на пути
Опубликованная вами строка JSON не соответствует классам. "[{\"id\":\"ServiceGroup1\",\"types\":[\"books\"],\"services\":[{ — это не сложный объект, это просто плоская строка. Код, создавший эту строку, не работает.
@PanagiotisKanavos Json действительно работает, если вы удалите его } и дважды десериализуете. Один раз, чтобы получить строку значения и десериализовать эту строку значения в список.
А это значит, что продюсер сломался. Двойная десериализация означает, что производитель сломан. Двойная десериализация не поможет. Когда этот производитель наконец исправит ошибку, «исправление» сломается.
@PanagiotisKanavos менее сломан, но, вероятно, предназначен. Я предполагаю, что сторонний API обрабатывает не только этот конкретный случай, но и некоторые другие. Это больше похоже на объект, у которого есть имя и значение. Затем это значение можно десериализовать в то, чем оно действительно должно быть. Что меня беспокоит, так это лишнее } если это из API, то что-то СИЛЬНО сломано, если это просто ошибка, то ничего страшного
\"names\":{\"en\":\"ServiceGroup2\"}}}]" это моя ошибка при копировании. исправлено и обновлено в вопросе. Спасибо, что сообщили мне





Вам нужно создать экземпляр List и присвоить ему значение. затем вы можете десериализовать объект с помощью Newtonsoft.Json.
См. код ниже:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Service
{
public int Id { get; set; }
public int CalendarId { get; set; }
public string PublicId { get; set; }
}
public class ServiceGroup
{
public string Id { get; set; }
public List<string> Types { get; set; }
public List<Service> Services { get; set; }
public Names Names { get; set; }
}
public class Names
{
[JsonProperty("en")]
public string English { get; set; }
}
public class ApiResponse
{
public string Name { get; set; }
public string Value { get; set; }
public List<ServiceGroup> ServicesGroups { get; set; } = new List<ServiceGroup> ();
}
class Program
{
static void Main()
{
string jsonResponse = @"{
""name"": ""servicesGroups"",
""value"": ""[
{\""id\"":\""ServiceGroup1\"",\""types\"":[\""books\""],\""services\"":[{\""id\"":2,\""calendarId\"":2,\""publicId\"":\""1234567890\""},{\""id\"":1,\""calendarId\"":1,\""publicId\"":\""0987654321\""}],\""names\"":{\""en\"":\""Service Group1\""}},
{\""id\"":\""ServiceGroup2\"",\""types\"":[\""books\""],\""services\"":[{\""id\"":2,\""calendarId\"":2,\""publicId\"":\""7575637576457457567\""} ,{\""id\"":1,\""calendarId\"":1,\""publicId\"":\""2143658709\""}],\""names\"":{\""en\"":\""ServiceGroup2\""}}
]""
}";
ApiResponse apiResponse = JsonConvert.DeserializeObject<ApiResponse>(jsonResponse);
Console.WriteLine($"Name: {apiResponse.Name}");
Console.WriteLine($"Value: {apiResponse.Value}");
foreach (var serviceGroup in apiResponse.ServicesGroups)
{
Console.WriteLine($"ServiceGroup ID: {serviceGroup.Id}, English Name: {serviceGroup.Names?.English}");
foreach (var service in serviceGroup.Services)
{
Console.WriteLine($" Service ID: {service.Id}, Calendar ID: {service.CalendarId}, Public ID: {service.PublicId}");
}
}
}
}
Работаю .Netfiddle здесь
Ваш json не такой, как мой. У вас есть лишние ". Я не могу контролировать json или сторонние API.
добавлен скриншот отладки с вашим кодом. Невозможно получить группы обслуживания
@PavanKumarGVVS у тебя плохой JSON. Что бы ни произвело, оно сломано. value не содержит массива объектов, он содержит плоскую строку с экранированными кавычками. Исправьте производителя вместо того, чтобы пытаться десериализовать сломанный JSON.
Хорошо, я постарался сохранить это как можно ближе к вашему исходному коду. Как уже упоминалось в @grek40, когда вы выполняете начальную десериализацию, вам нужно сделать значение строковым типом, поскольку это то, что на самом деле находится в вашем JSON. Затем вы можете десериализовать эту строку значений в свой список.
Итак, это новый класс, который я добавил, и модификация, которую я внес в ваш RootObject.
//This is what your Json will Deserialize into/ what you will have to Serialize to get the same JSON fromat
public class RootObjectWithValueString
{
public string name { get; set; }
public string value { get; set; }
public RootObject ToRootObject()
{
List<ServicesGroup> val = JsonConvert.DeserializeObject<List<ServicesGroup>>(value);
RootObject robj = new RootObject(){name = name, value = val};
return robj;
}
}
//This contains the values in a manner for you to work with
public class RootObject
{
public string name { get; set; }
public List<ServicesGroup> value { get; set; }
public RootObjectWithValueString ToROB()
{
string val = JsonConvert.SerializeObject(value);
RootObjectWithValueString rob = new RootObjectWithValueString(){name = name, value = val};
return rob;
}
}
И вот как можно десериализовать ваш JSON в ваш RootObject.
public void ResponseJsonToObject(string servicegroupsjson)
{
RootObjectWithValueString rob = JsonConvert.DeserializeObject<RootObjectWithValueString>(servicegroupsjson);
RootObject robj = rob.ToRootObject();
}
Теперь мне нужно упомянуть тот факт, что JSON, который вы нам предоставили, кажется ошибочным. В конце слишком много }. В \"names\":{\"en\":\"ServiceGroup2\"}}}]" у вас, конечно, есть один, чтобы закрыть имена, другой, чтобы закрыть Службу, но тогда у вас должен быть ], чтобы закрыть список. Вместо этого на пути есть }. Поэтому я не знаю, это просто ошибка, допущенная во время копирования json в stackoverflow, или это ошибка в самом json. теперь, если последнее так, это большая проблема.
\"names\":{\"en\":\"ServiceGroup2\"}}}]" это моя ошибка при копировании. правильный, обновленный, о котором идет речь. Спасибо, что сообщили мне
@PavanKumarGVVS ну, я думаю, теперь ты удалил один из многих XD. Но в какой-то момент это случается со всеми нами
@PavanKumarGVVS мой ответ тебе помог?
вам нужно исправить опубликованный вами json (добавьте «}» перед последним «]»), после этого я мог бы использовать этот код
var jObj=JObject.Parse(json);
var result = new RootObject {
name = (string) jObj["name"],
value = JsonConvert.DeserializeObject<List<ServicesGroup>>((string)jObj["value"])
};
или если вам нужно просто значение
List<ServicesGroup> value = JsonConvert.DeserializeObject<List<ServicesGroup>>(
(string)JObject.Parse(json)["value"]);
class RootObjectvalueсвойство должно быть строкой. Поскольку у вас есть вложенный сериализованный json, вам, вероятно, потребуются промежуточные типы для десериализации внешнего и внутреннего json, а затем объединения результатов в окончательную структуру объекта.