convert an array of array .. json in C# - c#

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.

Related

Insert comma into string where two brackets are touching (C#)

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
},{

Deserialize JSON array into string array

Say I have a string representing an array of objects in JSON form:
string s = "[{\"name\":\"Person1\"},{\"name\":\"Person2\"}]";
What I want is an array of strings, each string being the string representation of a JSON object - NOT the object itself. It should look something like this:
string[] s = new string[]
{
"{\"name\":\"Person1\"}",
"{\"name\":\"Person2\"}"
};
1) Almost every search I attempt pulls up millions of results on how to simply deserialize a JSON string using (eg) Json.NET. This is not what I want to do.
2) I have tried building a class representing the objects to temporarily loop through a deserialize/serialize mapping each to a string in an array, but the schema for the objects is variable (hence why I only need a string representation).
3) I have attempted a few regex to try and do this, but my JSON string can contain fields that contain JSON strings as their value (icky, but out of my control) and so nested character escaping etc drove me partially mad before I decided to beg for help here.
Surely this should be simple? Anybody got any pointers?
You'll need to deserialize it, and then serialize each object independently.
For example (using Newtonsoft.Json):
string json = "[{\"name\":\"Person1\"},{\"name\":\"Person2\"}]";
var objects = JsonConvert.DeserializeObject<List<object>>(json);
var result = objects.Select(obj => JsonConvert.SerializeObject(obj)).ToArray();
Yields (as a string[]):
{"name":"Person1"}
{"name":"Person2"}
If you try to avoid deserializing and serializing, you're almost certain to run into an edge case that will break your code.
string s = "[{\"name\":\"Person1\"},{\"name\":\"Person2\"}]";
var Json = JsonConvert.DeserializeObject<List<object>>(s);
string[] Jsonn = Json.Select(x => x.ToString()).ToArray();
[] Jsonn returns string array instead of object array with JObject formatted.
Hope this one help you.
Why don't you just use this
string s = "[{\"name\":\"Person1\"},{\"name\":\"Person2\"}]";
string[] t = s.Split(',');
I tried it. It simply gives you string array as you want it....

Get Length of array JSON.Net

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);
}

Convert String Into Dynamic Object

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"

Best way to deserialize a long string (response of an external web service)

I am querying a web service that was built by another developer. It returns a result set in a JSON-like format. I get three column values (I already know what the ordinal position of each column means):
[["Boston","142","JJK"],["Miami","111","QLA"],["Sacramento","042","PPT"]]
In reality, this result set can be thousands of records long.
What's the best way to parse this string?
I guess a JSON deserializer would be nice, but what is a good one to use in C#/.NET? I'm pretty sure the System.Runtime.Serialization.Json serializer won't work.
Using the built in libraries for asp.net (System.Runtime.Serialization and System.ServiceModel.Web) you can get what you want pretty easily:
string[][] parsed = null;
var jsonStr = #"[[""Boston"",""142"",""JJK""],[""Miami"",""111"",""QLA""],[""Sacramento"",""042"",""PPT""]]";
using (var ms = new System.IO.MemoryStream(System.Text.Encoding.Default.GetBytes(jsonStr)))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(string[][]));
parsed = serializer.ReadObject(ms) as string[][];
}
A little more complex example (which was my original answer)
First make a dummy class to use for serialization. It just needs one member to hold the result which should be of type string[][].
[DataContract]
public class Result
{
[DataMember(Name="d")]
public string[][] d { get; set; }
}
Then it's as simple as wrapping your result up like so: { "d": /your results/ }. See below for an example:
Result parsed = null;
var jsonStr = #"[[""Boston"",""142"",""JJK""],[""Miami"",""111"",""QLA""],[""Sacramento"",""042"",""PPT""]]";
using (var ms = new MemoryStream(Encoding.Default.GetBytes(string.Format(#"{{ ""d"": {0} }}", jsonStr))))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(Result));
parsed = serializer.ReadObject(ms) as Result;
}
How about this?
It sounds like you have a pretty simple format that you could write a custom parser for, since you don't always want to wait for it to parse and return the entire thing before it uses it.
I would just write a recursive parser that looks for the tokens "[", ",", "\"", and "]" and does the appropriate thing.

Categories

Resources