简体   繁体   中英

Parse a string containing several json objects into something more convenient

The crux of the problem here is that I don't know any C#, yet find myself adding a feature to some test infrastructure which happens to be written in C#. I suspect this question is entirely trivial and beg your patience in answering. My colleagues who originally wrote this stuff are all out of the office.

I am parsing a string representing one or more json objects. So far I can get the first object, but can't work out how to access the remainder.

public class demo
{
public void minimal()
{
    // Note - the input is not quite json! I.e. I don't have 
    // [{"Name" : "foo"}, {"Name" : "bar"}]
    // Each individual object is well formed, they just aren't in
    // a convenient array for easy parsing.
    // Each string representation of an object are literally concatenated.

    string data = @"{""Name"": ""foo""} {""Name"" : ""bar""}";

    System.Xml.XmlDictionaryReader jsonReader = 
       JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(data),
       new System.Xml.XmlDictionaryReaderQuotas());

    System.Xml.Linq.XElement root = XElement.Load(jsonReader);
    Assert.AreEqual(root.XPathSelectElement("//Name").Value, "foo");

    // The following clearly doesn't work
    Assert.AreEqual(root.XPathSelectElement("//Name").Value, "bar");
}
}

I'm roughly at the point of rolling enough of a parser to work out where to split the string by counting braces but am hoping that the library support will do this for me.

The ideal end result is a sequential datastructure of your choice (list, vector? don't care) containing one System.Xml.Linq.XElement for each json object embedded in the string.

Thanks!

edit: Roughly viable example, mostly due to George Richardson - I'm playing fast and loose with the type system (not sure dynamic is available in C#3.0), but the end result seems to be predictable.

public class demo
{
    private IEnumerable<Newtonsoft.Json.Linq.JObject>
            DeserializeObjects(string input)
    {
        var serializer = new JsonSerializer();
        using (var strreader = new StringReader(input))
        {
            using (var jsonreader = new JsonTextReader(strreader))
            {
                jsonreader.SupportMultipleContent = true;
                while (jsonreader.Read())
                {
                    yield return (Newtonsoft.Json.Linq.JObject)
                                  serializer.Deserialize(jsonreader);
                }
            }
        }
    }

    public void example()
    {
        string json = @"{""Name"": ""foo""} {""Name"" : ""bar""} {""Name"" : ""baz""}";
        var objects = DeserializeObjects(json);

        var array = objects.ToArray();
        Assert.AreEqual(3, array.Length);
        Assert.AreEqual(array[0]["Name"].ToString(), "foo");
        Assert.AreEqual(array[1]["Name"].ToString(), "bar");
        Assert.AreEqual(array[2]["Name"].ToString(), "baz");
    }
}

You are going to want to use JSON.net for your actual deserialization needs. The big problem I see here is that your json data is just being concatenated together which means you are going to have to extract each object from the string. Luckily json.net's JsonReader has a SupportMultipleContent property which does just this

public void Main()
{
    string json = @"{""Name"": ""foo""} {""Name"" : ""bar""} {""Name"" : ""baz""}";
    IEnumerable<dynamic> deserialized = DeserializeObjects(json);
    string name = deserialized.First().Name; //name is "foo"
}

IEnumerable<object> DeserializeObjects(string input)
{
    JsonSerializer serializer = new JsonSerializer();
    using (var strreader = new StringReader(input)) {
        using (var jsonreader = new JsonTextReader(strreader)) {
            jsonreader.SupportMultipleContent = true;
            while (jsonreader.Read()) {
                yield return serializer.Deserialize(jsonreader);
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM