Newtonsoft.Json не удалось преобразовать из JSON в ICollection <Object> - PullRequest
0 голосов
/ 04 марта 2019

Привет! У меня есть следующий JSON, и я хочу десериализовать в ICollection<Location>

"\ u0001 [{\" Id \ ": 1, \" Name \ ": \" A-01\ ", \" Address \ ": \" aa \ ", \" Children \ ": [{\" Id \ ": 2, \" Name \ ": \" A-01-01 \ ", \" Address\ ": \" bb \ ", \" Children \ ": [{\" Id \ ": 5, \" Name \ ": \" A-01-02-01 \ ", \" Address \ ": \"cc \"}]}, {\ "Id \": 3, \ "Name \": \ "A-01-02 \", \ "Address \": \ "dd \"}]}}, {\"Id \": 4, \ "Name \": \ "B-01 \", \ "Address \": \ "ee \", \ "Children \": [{\ "Id \": 6, \"Имя \": \ "B-01-01 \", \ "Адрес \": \ "ff \"}]}] "

для чтения JSON

[
  {
    "Id": 1,
    "Name": "A-01",
    "Address": "aa",
    "Children": [
      {
        "Id": 2,
        "Name": "A-01-01",
        "Address": "bb",
        "Children": [
          {
            "Id": 5,
            "Name": "A-01-02-01",
            "Address": "cc"
          }
        ]
      },
      {
        "Id": 3,
        "Name": "A-01-02",
        "Address": "dd"
      }
    ]
  },
  {
    "Id": 4,
    "Name": "B-01",
    "Address": "ee",
    "Children": [
      {
        "Id": 6,
        "Name": "B-01-01",
        "Address": "ff"
      }
    ]
  }
]

Местоположение объекта

public class Location
{
    [JsonProperty("Id")]
    public int Id { get; set; }

    [JsonProperty("Name")]
    [Required]
    public string Name { get; set; }

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

    public ICollection<Asset> Assets { get; set; }

    public Location ParentLocation { get; set; }

    [JsonProperty("Children")]
    public virtual ICollection<Location> ChildrenLocation { get; set; }

}

Я пытаюсь проверить строку очистки, но без надежды ..

    var jsonString = @"[{""Id"":1,""Name"":""A-01"",""Address"":""aa"",""Children"":[{""Id"":2,""Name"":""A-01-01"",""Address"":""bb",""Children"":[{""Id"":5,""Name"":""A-01-02-01"",""Address"":""cc""}]},{""Id"":3,""Name"":""A-01-02"",""Address"":""dd""}]},{""Id"":4,""Name"":""B-01"",""Address"":""ee"",""Children"":[{""Id"":6,""Name"":""B-01-01"",""Address"":""ff""}]}]";

    var locations = JsonConvert.DeserializeObject<ICollection<Location>>(jsonString.Trim());

ОШИБКА

Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: . Path '', line 0, position 0.
   at Newtonsoft.Json.JsonTextReader.ParseValue()
   at Newtonsoft.Json.JsonTextReader.Read()
   at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Ошибка очевидна, строка недопустима в формате JSON, и проблема заключается в самом первом символе, \u0001.

«Читаемая» строка JSON и тест обрезки не содержат этот символ, поэтому они не могут даже воспроизвести проблему.

Trim () не можетработа сама по себе.Его задача - удалить пробелы, но \u0001 является символом SOH (начало заголовка).Это , а не считается пробелом.

Чтобы на самом деле решить проблему, код, который создает этот символ, должен быть исправлен, чтобы он не его излучал.Если эти строки JSON происходят из потокового файла JSON, в котором в качестве разделителя записей используется SOH, его следует исправить, чтобы не не включал разделитель записей в строку JSON.

Если этоневозможно, перегрузка String.Trim (Char []) должна использоваться для удаления символа SHO:

var locations = JsonConvert.DeserializeObject(jsonString.Trim('\u0001'));

После удаления символа SOH десериализация работает очень хорошо:

var jsonString = "\u0001[{\"Id\": 1, \"Name\": \"A-01\", \"Address\": \"aa\", \"Children\": [{\"Id\": 2, \"Name\": \"A-01-01\", \"Address\": \"bb\", \"Children\": [{\"Id\": 5, \"Name\": \"A-01-02-01\", \"Address\": \"cc\"}]}, {\"Id\": 3, \"Name\": \"A-01-02\", \"Address\": \"dd\"}]}, {\"Id\": 4, \"Name\": \"B-01\", \"Address\": \"ee\", \"Children\": [{\"Id\": 6, \"Name\": \"B-01-01\", \"Address\": \"ff\"}]}]";
var cleaned=jsonString.Trim('\u0001');
var locations = (JArray)JsonConvert.DeserializeObject(cleaned);
Debug.Assert(locations.Count==2);

var address=(JValue)locations[1]["Children"][0]["Address"];
Debug.Assert(String.Equals(address.Value,"ff"));
0 голосов
/ 04 марта 2019

Как говорит Дай, есть символ "\ u0001" (см. описание ).Я думаю, что вы копируете его из какого-то места и вам это не нужно, поэтому вы можете просто удалить его:

  var str =
                "\u0001[{\"Id\": 1, \"Name\": \"A-01\", \"Address\": \"aa\", \"Children\": [{\"Id\": 2, \"Name\": \"A-01-01\", \"Address\": \"bb\", \"Children\": [{\"Id\": 5, \"Name\": \"A-01-02-01\", \"Address\": \"cc\"}]}, {\"Id\": 3, \"Name\": \"A-01-02\", \"Address\": \"dd\"}]}, {\"Id\": 4, \"Name\": \"B-01\", \"Address\": \"ee\", \"Children\": [{\"Id\": 6, \"Name\": \"B-01-01\", \"Address\": \"ff\"}]}]";
            var unescapeStr = str.Replace("\u0001", String.Empty);
            var result = JsonConvert.DeserializeObject<ICollection<Location>>(unescapeStr);

Символ "\ u0001" вообще не должен быть в вашей строке, не только при запуске,поэтому вы должны удалить его из всей строки, используя Replace not Trim

Вторая проблема в вашем тестовом коде.Когда вы копируете \ прошлую строку с какими-то специальными символами, Visual Studio спрашивает вас, хотите ли вы ее избежать, и если вы говорите «да», вы можете дважды экранировать символы

Поэтому попробуйте использовать для проверкистрока из примера выше

...