How can I get the length of a JSON Array I get using json.net in C#? After sending a SOAP call I get a JSON string as answer, I use json.net to parse it.
Example of the json I got:
{"JSONObject": [
{"Id":"ThisIsMyId","Value":"ThisIsMyValue"},
{"Id":"ThisIsMyId2","Value":"ThisIsMyValue2"}
]}
And I parse it and write it in console:
var test = JObject.Parse (json);
Console.WriteLine ("Id: {0} Value: {1}", (string)test["JSONObject"][0]["Id"], (string)test["JSONObject"][0]["Value"]);
This works like a spell, only I don't know the length of the JSONObject, but I need to do it in a for loop. I only have no idea how I can get the length of test["JSONObject"]
But something like test["JSONObject"].Length would be too easy I guess :(..
You can cast the object to a JArray and then use the Count property, like so:
JArray items = (JArray)test["JSONObject"];
int length = items.Count;
You can then loop the items as follows:
for (int i = 0; i < items.Count; i++)
{
var item = (JObject)items[i];
//do something with item
}
According to Onno (OP), you can also use the following:
int length = test["JSONObject"].Count();
However, I have not personally confirmed that this will work
The easiest and cleanest way I found:
int length = test["JSONObject"].Count;
You can use below line to get the length of JSON Array in .Net (JArray) .
int length = ((JArray)test["jsonObject"]).Count;
Just try this:
var test= ((Newtonsoft.Json.Linq.JArray)json).Count;
This worked for me supposing the json data is in a json file.
In this case, .Length works but no intellisence is available:
public ActionResult Index()
{
string jsonFilePath = "C:\\folder\\jsonLength.json";
var configFile = System.IO.File.ReadAllText(jsonFilePath);
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(configFile);
var jsonObject = d["JSONObject"];
int jsonObjectLength = jsonObject.Length;
return View(jsonObjectLength);
}
Related
I'm trying to write a JSON file in C#, and I have a problem where I want to seperate each object with a comma (',') for it to be valid JSON, however I can't figure out how to do this. I've searched if there is a way you can search for a specific pattern in a string (in my case it would be '}{') and a regular expression might work, but I don't know how to create one.
The final result should look like
'},{'
instead of
'}{'.
Here is my code so far:
private void loopThroughArray()
{
string json = "";
for (int i = 0; i < array.Count; i++)
{
MyObject t = array[i];
json += new JavaScriptSerializer().Serialize(t);
//this writes the json to the file but without comma seperator
}
System.IO.File.WriteAllText(#"<MyFilepath>\json.txt", "{\"json\":[" + json + "]}");
//this writes the json to a file that and is in a json array called 'json'
}
I looked at different ways of serialising JSON as per #Measuring 's suggestion and discovered that this was the easiest method in my opinion:
json = JsonConvert.SerializeObject(MyObject);
Works perfectly, thanks #Measuring!
I agree with #Measuring it seems like an over complication to write your own when there are tools which can be used as identified in this answer.
Nonetheless you could do the following...
string json = "";
for (int i = 0; i < array.Count; i++){
MyObject t = array[i];
json += new JavaScriptSerializer().Serialize(t);
}
string pattern = "\}{\";
string replacement = "},{";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(json, replacement);
What you are trying to do can be solved by string.Join and a bit of Linq
var serializer = new JavaScriptSerializer();
var json = string.Join( ",", array.Select( e => serializer.Serialize(e) );
Looks like this:
json += new JavaScriptSerializer().Serialize(t);
Is creating a {json object}. Your solution might be as easy as appending a , after like:
json += new JavaScriptSerializer().Serialize(t) + ",";
Edit (responding on your comment):
You can easily skip the last loop with an inner check.
json += new JavaScriptSerializer().Serialize(t);
if (i < array.Count - 1) json += ",";
Alternatively you could cut the for-loop 1 item short and add the last item after the loop.
It's far more efficient to use a StringBuilder than += and you should avoid creating reusable objects within loops.
Keeping as close to your code as possible, you could try:
private void loopThroughArray()
{
var serializer = new JavaScriptSerializer();
var json = new System.Text.StringBuilder();
for (int i = 0; i < array.Count; i++)
{
MyObject t = array[i];
json.Append(serializer.Serialize(t));
if (i < array.Count)
json.Append(",");
}
System.IO.File.WriteAllText(#"<MyFilepath>\json.txt", "{\"json\":[" + json.ToString() + "]}");
}
But it may be simpler to try:
private void loopThroughArray()
{
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(array);
System.IO.File.WriteAllText(#"<MyFilepath>\json.txt", "{\"json\":" + json.ToString() + "}");
}
But, if I were doing it I'd use Json.Net's JsonConvert on an anonymous type:
System.IO.File.WriteAllText(
#"<MyFilepath>\json.txt",
JsonConvert.SerializeObject(new {
json = array
}));
You can get Json.Net from nuget.
JsonNet is indeed easier to use, but in your case it feels like
JavaScriptSerializer works fine. Presumably you expect "{json:[...]}" as result - serializing new {json = array} instead of just array will produce that output:
var finalJson = new JavaScriptSerializer().Serialize(new {json = array});
Side note: please avoid manual string manipulation when constructing JSON or XML -it is not worth the effort and result in most cases is somewhat wrong.
Hi Kevin would it not be possible to replace the string using regex expressions,
/}{/g
and replace with
},{
given an apparently invalid json
(which comes from google)
https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=de&dt=t&q=Science
of
[[["Wissenschaft","Science",,,2]],,"en"]
i want to get the values of Wissenschaft and Science
if figured out a very inelegant way to do it with Json.net via
string h = "[[[\"Wissenschaft\",\"Science\",,,2]],,\"en\"] ";
var obj = JsonConvert.DeserializeObject<List<dynamic>>(h);
JArray arr1 = obj[0];
var arr2 = arr1.First;
var x = arr2.First.Next;
string s = x.ToString();
is there some better, less verbose way ?
Here is a more concise version, maybe somebody has one which also retains
the other values from the top array
string h = "[[[\"Wissenschaft\",\"Science\",,,2]],,\"en\"]";
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Error = (serializer, err) =>
{
err.ErrorContext.Handled = true;
//ignore all errors
};
var obj = JsonConvert.DeserializeObject<List<List<List<dynamic>>>>(h,settings);
string strWissenschaft = obj[0][0][0];
string strScience = obj[0][0][1];
As you see i only care for the values in the most nested array, the other values are lost.
For first this is not valid JSON object but nevermind as you said Json.NET will parse it by adding null values into empty commas.
Because this is not valid object and it is just an array in some JSON format. There will probably no better way then parse it into dynamic List as you already did.
In case of { } at start and end and some keys:values format you can deserialize it into C# object according to class which you can define.
I have a string in my C# model populated with this string:
"[{\"ta_id\":97497,\"partner_id\":\"229547\",\"partner_url\":\"http://partner.com/deeplink/to/229547\"},{\"ta_id\":97832,\"partner_id\":\"id34234\",\"partner_url\":\"http://partner.com/deeplink/to/id34234\"}]"
Is there a way, using LINQ or RegEx, that I could parse out the partner_id's - so I ended up with a list object with:
229547
id34234
Thanks for your help, Mark
I have never used any JSON parser but if it comes to Regex you could try something like this:
private static void regexString()
{
string myString = "[{\"ta_id\":97497,\"partner_id\":\"229547\",\"partner_url\":\"http://partner.com/deeplink/to/229547\"},{\"ta_id\":97832,\"partner_id\":\"id34234\",\"partner_url\":\"http://partner.com/deeplink/to/id34234\"}]";
string[] stringList = Regex.Split(myString, "},{");
for (int i=0; i<stringList.Length ;i++)
{
stringList[i] = Regex.Split(Regex.Split(stringList[i], "partner_id\\\":\\\"")[1], "\\\",\\\"partner_url\\\"")[0];
}
}
Also there is a nice website to help you with creating your own regex patterns in the future, check it out:
gskinner.com
And a nice and short tutorial:
www.codeproject.com
Assuming your link having partner id always-
string Name = "[{\"ta_id\":97497,\"partner_id\":\"229547\",\"partner_url\":\"http://partner.com/deeplink/to/229547\"},{\"ta_id\":97832,\"partner_id\":\"id34234\",\"partner_url\":\"http://partner.com/deeplink/to/id34234\"}]";
string[] splittedString = Regex.Split(Name, "}");
List<string> allIds = new List<string>();
foreach (var i in splittedString)
{
var ids =Regex.Split(i, "/");
string id = ids[ids.Length - 1];
allIds.Add(id);
}
If that is the general format of the string then this regex should work
(?i)(?<=(partner_id).{5})\w+
Test here
This from your string will get
229547 and id34234
(?i) = Case insesitivity
(?<=(partner_id).{5}) = postive lookbehind for parter_id then any 5 characters which in this case will be \":\"
\w+ = Any alphanumeric characters one or more times
Hope this helped
Since this is JSON, you probably shouldn't bother trying to get a regex working. Instead, you can parse the JSON and then use LINQ.
using System.Web.Script.Serialization; // (in System.Web.Extensions.dll)
...
string s = "[{\"ta_id\":97497,\"partner_id\":\"229547\",\"partner_url\":\"http://partner.com/deeplink/to/229547\"},{\"ta_id\":97832,\"partner_id\":\"id34234\",\"partner_url\":\"http://partner.com/deeplink/to/id34234\"}]";
JavaScriptSerializer j = new JavaScriptSerializer();
object[] objects = (object[])j.DeserializeObject(s);
string[] ids = objects.Cast<Dictionary<string, object>>()
.Select(dict => (string)dict["partner_id"])
.ToArray();
It's a little messy to deserialize it to an object, because you don't have any type information. If you're not afraid of making a small class to deserialize into, you can do something like this:
class Foo
{
public string partner_id
{
get;
set;
}
}
...
JavaScriptSerializer j = new JavaScriptSerializer();
string[] ids = j.Deserialize<Foo[]>(s).Select(x => x.partner_id).ToArray();
Note that there are other options for deserializing JSON. I simply chose the most general-purpose one that's built in.
Is there a straightforward way of converting:
string str = "a=1,b=2,c=3";
into:
dynamic d = new { a = 1, b = 2, c = 3 };
I think I could probably write a function that splits the string and loops the results to create the dynamic object. I was just wondering if there was a more elegant way of doing this.
I think if you convert the "=" into ":" and wrap everything with curly brackets you'll get a valid JSON string.
You can then use JSON.NET to deserialize it into a dynamic object:
dynamic d = JsonConvert.DeserializeObject<dynamic>(jsonString);
You'll get what you want.
You may use Microsoft Roslyn (here's the all-in-one NuGet package):
class Program
{
static void Main(string[] args)
{
string str = "a=1,b=2,c=3,d=\"4=four\"";
string script = String.Format("new {{ {0} }}",str);
var engine = new ScriptEngine();
dynamic d = engine.CreateSession().Execute(script);
}
}
And if you want to add even more complex types:
string str = "a=1,b=2,c=3,d=\"4=four\",e=Guid.NewGuid()";
...
engine.AddReference(typeof(System.Guid).Assembly);
engine.ImportNamespace("System");
...
dynamic d = engine.CreateSession().Execute(script);
Based on the question in your comment, there are code injection vulnerabilities. Add the System reference and namespace as shown right above, then replace the str with:
string str =
#" a=1, oops = (new Func<int>(() => {
Console.WriteLine(
""Security incident!!! User {0}\\{1} exposed "",
Environment.UserDomainName,
Environment.UserName);
return 1;
})).Invoke() ";
The question you described is something like deserialization, that is, contructing objects from data form(like string, byte array, stream, etc). Hope this link helps: http://msdn.microsoft.com/en-us/library/vstudio/ms233843.aspx
Here's a solution using ExpandoObject to store it after parsing it yourself. Right now it adds all values as strings, but you could add some parsing to try to turn it into a double, int, or long (you'd probably want to try it in that order).
static dynamic Parse(string str)
{
IDictionary<String, Object> obj = new ExpandoObject();
foreach (var assignment in str.Split(','))
{
var sections = assignment.Split('=');
obj.Add(sections[0], sections[1]);
}
return obj;
}
Use it like:
dynamic d = Parse("a=1,b=2,c=3");
// d.a is "1"
I have the following object:
public class TestModel
{
public object TestValue { get; set; }
}
My database contains strings in JSON format e.g.
string dbValue1 = "[\"test value\"]"
string dbValue2 = "[\"one value\",[\"another value|or this value\"]]"
int dbValue3 = 1
bool dbValue4 = true
And I need to deserialize these values to the TestModel.TestValue property so that when I serialize the object I get the same format that is stored in the database. I can obviously get an int or bool an a basic array to work, but I can't in the case of a slightly more complex array. From the dbValue2 above I would want the output to be:
"testValue" : ["one value",["another value|or this value"]]
Now, I am using ServiceStack.Text and so far this is what I've tried:
TestValue = JsonSerializer.DeserializeFromString(dbValue, typeof(object))
TestValue = dbValue.FromJson<object>()
TestValue = JsonObject.Parse(dbValue)
And these generate:
"testValue":"[one value,[another value|or this value]]"
"testValue":{"one value":["another value|or this value"]}
"testValue":{"one value":["another value|or this value"]}
I can understand why these would not work, but I can't figure out how to do what I need.
Any help would be much appreciated.
It is because the root element is an array in the JSON. ServiceStack seems to choke on that.
If you try it with ServiceStack and add a root object with the same array as a property e.g.
var json = "{\"root\":[\"one value\",[\"another value|or this value\"]]}";
var testValue = JsonObject.Parse(json);
Console.WriteLine(testValue.ToJson());
It serializes the array correctly.
Json.Net seems to just work though.
var json = "[\"one value\",[\"another value|or this value\"]]";
var testValue = JsonConvert.DeserializeObject(
Console.WriteLine(JsonConvert.SerializeObject(testValue));
Annoying :)