Newtonsoft.JSON блокирует десериализацию объекта, заключенного в двойные кавычки в массиве

#c# #json #json.net

Вопрос:

Я сериализуюа с List<UserDataJson> помощью Newtonsoft.JSON и последующая запись в файл. Вот класс:

 private class UserDataJson
{
    public UserDataJson() { }

    public UserDataJson(string path)
    {
        Location = path;
        Opacity = 1;
    }

    public UserDataJson(IUserData userData)
    {
        Location = userData.Location;
        Opacity = userData.Opacity;
    }

    public string Location { get; set; }

    public double Opacity { get; set; }
}
 

Код, который сериализует и записывает:

 private static readonly string _userDataFile = Path.Combine(_programDataFolder, "userdata.json");

...

public void SaveData(IReadOnlyCollection<IUserData> userData)
{
     File.WriteAllText(_userDataFile, JsonConvert.SerializeObject(userData.Select(Serialize).ToList(), Formatting.Indented));
}

private static string Serialize(IUserData userData) => JsonConvert.SerializeObject(new UserDataJson(userData));
 

При использовании одного элемента создается _userDataJson файл, который выглядит следующим образом:

 [
  "{"Location":"C:\\Users\\me\\Documents\\test.txt","Opacity":1.0}"
]
 

Однако, когда я пытаюсь десериализовать, я получаю JsonSerializationException :

Десериализация:

 JsonConvert.DeserializeObject<List<UserDataJson>>(File.ReadAllText(_userDataFile).Replace("\\", "\");
 

Исключение:

{"Error converting value "{"Location":"C:\Users\me\Documents\test.txt","Opacity":1.0}" to type 'Company.App.Wpf.MainWindow.UserDataService UserDataJson'. Path '[0]', line 2, position 73."}

Внутреннее исключение:

"Could not cast or convert from System.String to Company.App.Wpf.MainWindow.UserDataService UserDataJson."

Однако, когда я удаляю escape-символ из двойных кавычек и удаляю двойные кавычки вокруг объекта в целом, тогда он десериализуется нормально.

 [
  {"Location":"C:\\Users\\me\\Documents\\test.txt","Opacity":1.0}
]
 

Есть ли какая-либо конфигурация, которую я должен применять на этапе сериализации или десериализации, чтобы создать строку, которую можно десериализовать в список UserDataJson ?

Комментарии:

1. Это не объект, это обычная старая строка. В коде, который вызвал это, есть ошибка, а не в JSON.NET . Что-то, заключенное в двойные кавычки в JSON, является строкой, независимо от того, что она содержит

2. Представьте, что вы берете объект и сериализуете его как JSON. Вы получаете строку, верно? Поэтому, если вы добавите эту строку в список и сериализуете список, вы получите что-то вроде вашего JSON выше. Это связано с этой частью вашего Serialize кода : .Select(Serialize) . Этот шаг вообще не кажется необходимым.

3. Спасибо @Llama, вы правы. Если вы ответите на вопрос таким образом, я соглашусь.

Ответ №1:

Представьте, что вы берете объект и сериализуете его как JSON. Вы получаете строку, верно? Поэтому, если вы добавите эту строку в список и сериализуете список, вы получите что-то вроде вашего JSON выше.

Это связано с этой частью вашего кода сериализации : .Select(Serialize) . Этот шаг вообще не кажется необходимым.

Удалив это, мы получаем следующее:

 public void SaveData(IReadOnlyCollection<IUserData> userData)
{
     File.WriteAllText(_userDataFile, JsonConvert.SerializeObject(userData, Formatting.Indented));
}

private static string Serialize(IUserData userData) => JsonConvert.SerializeObject(new UserDataJson(userData));
 

И теперь этот код должен работать для десериализации результирующего JSON:

 var result = JsonConvert.DeserializeObject<List<UserDataJson>>(File.ReadAllText(_userDataFile));
 

Попробуйте это онлайн

Комментарии:

1. Просто в качестве примечания мне пришлось изменить IReadOnlyCollection<IUserData> IReadOnlyList<IUserData> на, чтобы перейти userData непосредственно в SerializeObject .