Converting string with list of Jarray Objects to JSONin C# - c#

I have a JSON string like
string str = [{"a":"b"},{"c":"d"}],
I converted it to Jarray with the below code,
JArray obj=JArray.Parse(str);
Its working fine, but my input string got changed to
str=[{"a":"b"},{"c":"d"}],[{"e":"f"},{"g":"h"}]
Now the JArray parsing is throwing me an error as its a list of JArray, How can i parse the above string in C#?

I was able to find a way to parse the following string using JsonReader.SupportMultipleContent:
[{"a":"b"},{"c":"d"}],[{"e":"f"},{"g":"h"}]
Thanks #dbc for pointing me in the right direction (see Additional text encountered after finished reading JSON content).
Please note that this functionality is available only from Release 11.0.1 of Json.NET.
The following method uses a JsonTextReader and returns a IEnumerable<KeyValuePair<string, string>>:
private static IEnumerable<KeyValuePair<string, string>> ParseKeyValuePairs(string json)
{
using (var reader = new StringReader(json))
using (var jsonReader = new JsonTextReader(reader) { SupportMultipleContent = true })
{
JsonSerializer serializer = JsonSerializer.CreateDefault();
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonToken.Comment)
{
continue;
}
var dictionaries = serializer.Deserialize<List<Dictionary<string, string>>>(jsonReader);
foreach (KeyValuePair<string, string> keyValue in dictionaries.SelectMany(x => x))
{
yield return keyValue;
}
}
}
}
Using the code to generate a Dictionary<string, string>:
string json = #"[{""a"":""b""},{""c"":""d""}],[{""e"":""f""},{""g"":""h""}]";
Dictionary<string, string> data = ParseKeyValuePairs(json).ToDictionary(x => x.Key, x => x.Value);
Result:

Related

How to deserialize JSON to IList<KeyValuePair<string, object>> with whitespaces in key?

I have a big problem with deserializing my JSON to an object. It should be deserialized to IList<KeyValuePair<string, object>> the problem is that the keys have white spaces.
"spec": {
"SOMETHING WITH SPACES" : "10"
etc.
...
}
public class SomeObject
{
...
public IList<KeyValuePair<string, object>> spec{ get; set; }
...
}
Deserializing code:
var sr = new ServiceStack.Text.JsonSerializer<SomeObject>();
var esResult = sr.DeserializeFromString(responseJson);
responseJson is a GET from ElasticSearch.
What I get to my field it is null.
If I have key without whitespaces it's deserializing normally and I'm getting my IList<KeyValuePair<string, object>>
You can't use IList or List here, because your source JSON has no [ ] in it, which is a requirement if you want to parse into such a collection. In other words, without [ ] you can't parse into a collection, at least not without going through lots of hoops.
Instead you need to use a Dictionary as was suggested already in comments.
Note: I used Newtonsoft JsonConvert because you didn't state what your parser is, but that should make little or no difference to my arguments.
Working code:
var json = "{ \"spec\": { \"SOMETHING WITH SPACES\" : \"10\" } }";
var someObj = JsonConvert.DeserializeObject<SomeObject>(json);
public class SomeObject
{
public Dictionary<string, object> spec{ get; set; }
}
After that, you can cast the spec property to an IEnumerable and loop through whatever was found:
foreach (var pair in someObj.spec as IEnumerable<KeyValuePair<string, object>>)
{
Console.WriteLine(pair.Key + " -> " + pair.Value);
}
Or even convert it to a List:
var list = someObj.spec.ToList();
foreach (var pair in list)
{
Console.WriteLine(pair.Key + " -> " + pair.Value);
}
.NET Fiddle: https://dotnetfiddle.net/15l2R3
If you don't mind using Newtonsoft.Json:
const string json = #"{""spec"": { ""SOMETHING WITH SPACES"" : ""10"", ""SOMETHING WITH MORE SPACES"" : ""20"" }}";
dynamic data = JsonConvert.DeserializeObject(json);
Dictionary<string, string> list = data["spec"].ToObject<Dictionary<string, string>>();
foreach (var item in list)
{
Console.WriteLine(item.Key + ", " + item.Value);
}
I guess your JSON serialiazer makes some trouble. I'd recommend to use Newtonsoft.Json (in NuGet)
I've tried following code, and it works fine:
var o1 = new SomeObject() { spec = new List<KeyValuePair<string, object>>() };
o1.spec.Add(new KeyValuePair<string, object>("test with spaces", 10));
var r1 = Newtonsoft.Json.JsonConvert.SerializeObject(o1);
Console.WriteLine(r1);
var o2 = Newtonsoft.Json.JsonConvert.DeserializeObject<SomeObject>(r1);
var r2 = Newtonsoft.Json.JsonConvert.SerializeObject(o2);
Console.WriteLine(r2);
The outcome is
{"spec":[{"Key":"test with spaces","Value":10}]}
{"spec":[{"Key":"test with spaces","Value":10}]}
No null values, all works fine.
EDIT: I actually see no reason, why spaces should be any problem at all. They are just part of the string.

How to serialize a multiple list of elements in Json?

I have a JSON that looks like this:
{
"Identifier1":"TextOfIdentifier1",
"Identifier2":"TextOfIdentifier2",
"Identifier3":"TextOfIdentifier3",
...
}
I know how to deseralize a JSON into a custom object, I followed what says here, but all identifiers appear in the same JSON tag...
How can I get all identifiers inside the JSON?
The solution is like this in my case:
using (StreamReader r = new StreamReader(path))
{
string json = r.ReadToEnd();
JObject jsonLines = JObject.Parse(json);
foreach (var token in jsonLines)
{
dtos.Add(new TokenDto { HalId = token.Key, SourceText = token.Value.ToString() });
}
}
You can traverse JSON (similar to XDocument):
var json = "{\"Identifier1\":\"TextOfIdentifier1\",\"Identifier2\":\"TextOfIdentifier2\",\"Identifier3\":\"TextOfIdentifier3\"}";
foreach (var token in JObject.Parse(json).Children())
Console.WriteLine(token.Path);
Result:
Identifier1
Identifier2
Identifier3

C#: get the value of a key in an object using regex

I have a key with random bits of string in it making it difficult to extract it's value. How would I go about doing it when I don't know the random bits ahead of time?
given:
sample = {\"total_ra4jhga987y3h_power\": 30}
Is it possible to do something directly like
dynamic obj = JsonConvert.DeserializeObject(sample);
obj[#"^total_(.*)_power$"] ---> should give me 30
Use LINQ to JSON instead. If you parse it as a JObject, you can iterate over all the properties, and find those which match your regex.
Regex regex = new Regex(...);
JObject json = JObject.Parse(text);
foreach (var property in json.Properties())
{
if (regex.IsMatch(property.Name))
{
...
}
}
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string,long>>(sample);
Regex rg = new Regex("total_.*_power");
var key = jsonDict.Keys.First(k=>rg.IsMatch(k));
Console.log(jsonDict[key]);
You can utilize LINQ to go through your properties and test their names for your regexp:
public static class JsonExtensions
{
public static Dictionary<string, JToken> PropertiesByRegexp(this JObject token, Regex regex)
{
return token.Properties()
.Where(p => regex.IsMatch(p.Name))
.ToDictionary(p => p.Name, p => p.Value);
}
}
You can now use this extensions method in the following way:
JObject sample = JsonConvert.DeserializeObject("{\"total_ra4jhga987y3h_power\": 30, \"not_matching\": 31}") as JObject;
var result = sample.PropertiesByRegexp(new Regex("^total_(.*)_power$"));
foreach (var propertyPair in result)
{
Console.WriteLine($"{propertyPair.Key}: {propertyPair.Value}");
}
Outputs:
total_ra4jhga987y3h_power: 30

Read Json object and put the values in a List of string

Platform: C#
IDE: Visual Studio 2010
I am trying to read all the values from json object and put it in the list of string , for which I am doing Json deserialize but it throws me error...
Here is what I have tried
List<string> lstPName = new List<string>();
JavaScriptSerializer strJsonSer = new JavaScriptSerializer();
localhost.Pstats objStats = new localhost.Pstats();
var strJson = objStats.GetAutoCompleteData(txtSearchBox.Text.Trim());
lstPName = strJsonSer.DeserializeObject<string>(strJson);
Here is what the Json object holds
[{"PlayerName":"WA Mota"},{"PlayerName":"Atif Ahmed"}]
So, I need the player name value to be added in the list...
Simple and straightforward solution:
var strJson = "[{\"PlayerName\":\"WA Mota\"},{\"PlayerName\":\"Atif Ahmed\"}]";
var strJsonSer = new JavaScriptSerializer();
var list = new List<string>();
var result = strJsonSer.DeserializeObject(strJson) as object[];
if (result != null)
{
foreach (Dictionary<string, object> x in result)
{
list.Add(x["PlayerName"].ToString());
}
}
Or, if you are preferring LINQ - you can use instead of foreach loop something like:
list = result
.Cast<Dictionary<string, object>>()
.Select(x => x["PlayerName"].ToString())
.ToList();
Key idea: DeserializeObject used for parsing JSON data like yours gives you array of Dictionary<string, object> where key is JSON property name and value is JSON property value. Size of array equals to objects count in your JSON data.

String parsing (splitting and retrieving parameters)

I have a string formatted this way:
<?TAG param1="val1" parm2="val2" paramN="valN" /><?TAG param1="val1" parm2="val2" paramN="valN"/><?TAG param1="val1" parm2="val2" paramN="valN"/>
"TAG" is always the same value, but number of occurrences is variable and the number of parameters for each occurrence too. I can't change the source format.
I need to get the list of parameters for each occurrence using C# (.NET 4.0) Can you help me out?
XElement rootElement = XElement.Parse(string.Format("<element>{0}</element>",
yourString.Replace("?TAG", "TAG")));
var elements = rootElement.Elements();
var yourResult = elements.Select(x => new TagsAndParams { Tag = x,
Params = x.Attributes.Where(xa => xa.Name.LocalName.BeginsWith("param") });
With this class as a result holder (I know I could use anonymous types, but this is better for passing to other functions):
public class TagsAndParams
{
XElement Tag;
IEnumerable<XAttribute> Params;
}
You could do it with a nasty looking RegEx, but I'd make sure it's not actually an XML PI chain first:
(?<tag><?TAG (?<parm>param\d{1,2}=\"[^\"]+\"\s*)*\/\>)*
This will match groups, each group containing:
full tag
paramX="valX" pair
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
class ExampleClass
{
static void Main(string[] args)
{
string example = "<?TAG param1=\"val1\" param2=\"val2\" paramN=\"valN\" /><?TAG param1=\"val1\" param2=\"val2\" paramN=\"valN\"/><?TAG param1=\"val1\" param2=\"val2\" paramN=\"valN\"/>";
List<Dictionary<string, string>> result = new List<Dictionary<string, string>>();
string[] tokens = Regex.Split(example, "/><\\?TAG|<\\?TAG|/>");
foreach (string token in tokens) if (token.Length > 0)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
string[] parms = token.Split(' ');
foreach (string parm in parms) if (parm.Length > 0)
{
string[] keyvalue = Regex.Split(parm, "=\"|\"");
parameters.Add(keyvalue[0], keyvalue[1]);
}
result.Add(parameters);
}
Console.WriteLine("TAGs detected: " + result.Count);
foreach (Dictionary<string, string> token in result)
{
Console.WriteLine("TAG");
foreach (KeyValuePair<string, string> kvp in token)
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
}
}
I've finally solved using this code (provided by a friend of mine). The trick was the Regex used for splitting individual elements. Thank you for the support, I will make use of the tip about xml parser in future :)

Categories