Как динамически десериализовать Json String - PullRequest
0 голосов
/ 16 января 2019

Я использую данные опроса через SSE Stream, что дает мне ответы каждого человека построчно с этим форматом для Survey X:

{"data":["4482359","12526","5","5","","Yes, that is right","1"]}

Я прочитал это в List(of String), используя Streamreader

 Dim sr As StreamReader = New StreamReader(stream)
 Dim myList As List(Of String) = New List(Of String)

 While sr.Peek >= 0
     myList.Add(sr.ReadLine())
 End While

Теперь я хочу десериализовать строки, чтобы получить записи в свойствах класса (назовем его tmpUserData), к которому я могу получить доступ. Я пробовал это с помощью Newtonsoft.Json:

Dim tmpUserData As Object = JsonConvert.DeserializeObject(Of Object)(myList(i))

но, глядя на tmpUserData, десериализация не разделяет записи как

(1) User1
  (1) "4482359"
  (2) "12526"
  (3) "5"
  (4) ""
...    
(2) User1
  (1) "5847895"
  (2) "33568"
  (3) "6"
  (4) "2"
...

но вместо этого он просто помещает все в одну запись

(1) "4482359","12526","5","5","","Yes, that is right","1"

Причина, по которой я не могу просто написать класс и поместить в него данные, как

JsonConvert.DeserializeObject(myclass)(myList(i))

заключается в том, что это должно быть динамически, поскольку количество и структура строк различаются для разных обследований. Так что Survey Y может выглядеть так:

{"data":["Peter","Jackson","Albert Street","5","","1"]}

Может ли кто-нибудь помочь мне получить то, что я ищу, чтобы записи каждого участника Survery были правильно десериализованы? C# Решение также приветствуется.

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Предполагая, что это содержимое потока:

{"data":["4482359","12526","5","5","","Yes, that is right","1"]}
{"data":["2223446","65432","3","3","","Nope, that's not right","0"]}
(...)

Вы можете десериализовать эти строки, используя List<class>. Как то так:

using System.IO;
using Newtonsoft.Json;

public class RootObject
{
    public List<string> data { get; set; }
}

Потоковая передача JSON может быть десериализована двумя простыми способами:

  • Если вам действительно не нужно анализировать поток построчно, прочитайте поток до конца, затем используйте JsonTextReader для чтения полученной строки и JsonSerializer для десериализации результат чтения в экземпляр класса, который вы используете в качестве контейнера для данных:

List<RootObject> dataObjects = new List<RootObject>();

using (StreamReader sr = new StreamReader(stream))
{
    var JSONObject = sr.ReadToEnd();
    var reader = new JsonTextReader(new StringReader(JSONObject)) { SupportMultipleContent = true };
    var serializer = new JsonSerializer();

    while (reader.Read()) {
        dataObjects.Add(serializer.Deserialize<RootObject>(reader));
    }
    reader.Close();
}

VB.Net версия:

Imports System.IO
Imports Newtonsoft.Json

Public Class RootObject
    Public Property MyData As List(Of String)
End Class

Dim dataObjects As New List(Of RootObject)()
Using sr As New StreamReader(stream)
    Dim JSONObject As String = sr.ReadToEnd()

    Dim reader = New JsonTextReader(New StringReader(JSONObject)) With {
        .SupportMultipleContent = True
    }
    Dim serializer = New JsonSerializer()
    While reader.Read()
        dataObjects.Add(serializer.Deserialize(Of RootObject)(reader))
    End While
    reader.Close()
End Using
  • Если вам нужно анализировать поток построчно по какой-то причине, не указанной здесь, вы можете вставить разделитель массива [ перед первой строкой и ] после последней строки, разделяя каждую строку знаком (запятая) , Теперь у вас есть функциональный массив, который можно десериализовать с помощью JsonConvert.DeserializeObject<Object>(JSON)

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

[ {"data":["value1","value2","value3", (...)]},
  {"data":["value1","value2","value3", (...)]} ]

List<RootObject> dataObjects = new List<RootObject>();

using (StreamReader sr = new StreamReader(stream))
{
    var JSONObject = sr.ReadToEnd();
    dataObjects = JsonConvert.DeserializeObject<List<RootObject>>(JSONObject);
}

VB.Net версия:

Dim dataObjects As New List(Of RootObject)()

Using sr As New StreamReader(stream)
    Dim JSONObject As String = sr.ReadToEnd()
    dataObjects = JsonConvert.DeserializeObject(Of List(Of RootObject))(JSONObject)
End Using
0 голосов
/ 16 января 2019

почему вы используете StreamReader для чтения данных JSON?

вы можете использовать JObject для анализа вашего json и получения данных из него.

var json = @"{""data"":[""4482359"",""12526"",""5"",""5"","""",""Yes, that is right"",""1""]}";
var obj = JObject.Parse(json);

List<string> lst = (obj["data"]).ToObject<List<string>>();

var result = JsonConvert.SerializeObject(lst);
...