Страницы

Поиск по вопросам

суббота, 20 октября 2018 г.

Как правильно парсить json C#

Есть json, в котором хранятся точки, из которых, в последствии, строятся определенные 3d объекты, по сути координаты вершин. Особенность в том что лежат они на неравномерной глубине.

Как видно в 31-ом "наборе" точек они лежат сразу после узла "coordinates" а в 32-ом после этого узла они делятся еще на 2 группы, а внутри группы уже искомый набор точек. Задача состоит в том что бы дойти по узлам до элементов составляющих наборы точек (зеленые элементы являются координатами собственно x y), собрать точки принадлежащие одному набору в список, отправить их на обработку и дальше двигаться по json'у. Сложность в том, что там где они делятся на группы (32-ой), надо каждую группу элементов отправлять отдельно, как если бы это была законченная (как в случае с 31-ой, прошлись по 0,1,2 собрали точки внутри отправили пошли дальше), то есть зайти 32-geometry->coordinates->0 все что внутри собрать и отправить затем в 32-geometry->coordinate->1 собрать отправить, затем только дальше. Логично было бы предположить что там где type: MultiLineString можно просто добавить еще один цикл прохода по элементам, но что то мне подсказывает что я неверно рассуждаю. Как решить эту задачу правильно с точки зрения практик парсинга json файлов?
Извините за сумбурное описание, пытался детализировать как мог.
update вот таким образом я пытался добраться до необходимых мне данных, но данные из 32-ой группы сливались в один list и я так и не придумал как ПРАВИЛЬНО, мне их получить. Сейчас я понимаю судя по комментариям и ответам что я подобрался к задаче с принципиально не той стороны.
private void CreateRoads(JSONObject mapData) { int count = 0; foreach (var geo in mapData["features"].list) { count++; var l = new List();
for (int i = 0; i < geo["geometry"]["coordinates"].list.Count; i++) { if (!geo["geometry"]["coordinates"][i][0].IsNumber) {
for (int j = 0; j < geo["geometry"]["coordinates"][i].list.Count; j++) { var c = geo["geometry"]["coordinates"][i][j]; var bm = GM.LatLonToMeters(c[1].f, c[0].f); var pm = new Vector2(bm.x - Rect.center.x, bm.y - Rect.center.y); l.Add(pm.ToVector3xz()); } } else { var c = geo["geometry"]["coordinates"][i]; var bm = GM.LatLonToMeters(c[1].f, c[0].f); var pm = new Vector2(bm.x - Rect.center.x, bm.y - Rect.center.y); l.Add(pm.ToVector3xz()); } }
var m = new GameObject("road_" + count.ToString()).AddComponent(); m.transform.localPosition = new Vector3(m.transform.localPosition.x, m.transform.localPosition.y + 1f, m.transform.localPosition.z); m.transform.parent = this.transform; try { m.Initialize(geo["properties"]["id"].str, this, l, geo["properties"]["kind"].str); } catch (Exception ex) { Debug.Log(ex); } } }
с десериализацией я справился, спасибо @sp7, но как разрулить разные уровни глубины у блоков пока не пойму. Что бы это было универсально, а не хардкодом. Есть мысли на тему прохода в глубину до последнего узла (отличается тем что у него чайлдов видимо) от него вверх на уровень, собираем искомые данные (списки с координатами), отправляем, уровень вверх выходим, смотрим есть ли еще на это же уровне какие то списки, нету снова вверх если вышли до блока coordinates, то переходим к следующему номеру (33,34,35) и тд...вот беда только в том что я не знаю как такой проход в глубину сделать. И гугление не помогло особо =/
var root = JsonConvert.DeserializeObject(www.text); var features = root.roads.features; List coordinates = new List(); for (int i = 0; i < features.Length; i++) { coordinates.Add(features[i].geometry.coordinates); } ConstructRoad(coordinates);


Ответ

Позволю себе высказаться. Как ранее было замечено, для того что бы было удобно работать с Json данными, их нужно как минимум десериализовать в объектный вид.
Поэтому:
1) Если у вас есть эти Json данные в текстовом виде (string) скопируйте их в буфер обмена. Если данных в текстовом виде нет, получите их откуда-то из вне, преобразуйте в строку (как вариант, JObject.Parse().ToString()) и скопируйте в буфер обмена.
2) Создайте пустой С# файл, в нем не должно быть ничего, кроме указания namespace. Курсор ставим внутрь namespace
3) Затем в Visual Studio заходим в меню Edit -> Paste Special -> Paste JSON as Classes
4) Вуаля!!! Visual Studio создала за вас классы, которые представляют указанные Json данные.
5) Теперь когда классы С# готовы, Вы можете ваши Json данные используя JsonSerializer десериализовать в ту объектную модель, что за вас создала студия.
var root = JsonConvert.DeserializeObject(jsonStr);
6) Ну и в завершении, теперь Вы просто можете работать с данными в удобном виде.

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

Отправить комментарий