I am trying to parse JSON string in C# solution, but I can't get the internal/nested arrays which start with : ",[["bd felek",0],["bdm",0],["bd",0],["bdz",
["bd",[["bd felek",0],["bdm",0],["bd",0],["bdz",0,[131]],["bd fleke",0],["bd felek dfdf",0],["bdz dance practice",0,[3]],["bdz twice live",0,[131]],["bdo",0,[131]],["bd mawlaya",0]],{"a":"Uwt304b6at0ZtuU8mv8D5AyWS8wg6AQJQbYlPPS8knOVvcG","e":"1","j":"6l","k":1,"q":"ZQXxB0vG-GaPEF2RNib3gbVRXt0"}]
var jsonser = new JavaScriptSerializer();
var obj = jsonser.Deserialize<dynamic>(SourceCodeTxt.Text);
foreach (var x in obj)
{
// MessageBox.Show(x);
String strvalue = x["value"];
}
}
Your code should be looking at the second index (1) of the deserialized object:
foreach (var x in obj[1])
{
var value1 = x[0]; // bd felek
var value2 = x[1]; // 0
}
You want to use JSON.NET to better handle JSON. then you can simply do the following:
using Newtonsoft.Json.Linq;
...
JToken obj = JToken.Parse(/* Your JSON string goes in here */);
foreach (var x in obj[1])
{
var value1 = x[0]; // bd felek
var value2 = x[1]; // 0
...
}
Related
I have struggled to finish this task, please if anyone can give me a hint I would be so thankful.
My main task is to get data from database using (FOR JSON AUTO) which is working :)
select filed1, field2, field3 from table FOR JSON AUTO;
And then after connecting to Data base I use the StringBuilder() to build a Json Array of objects which is working :)
var jsonResult = new StringBuilder();
if(!r.HasRows)
{
jsonResult.Append("[]");
}
else
{
while(r.Read())
{
jsonResult.Append(r.GetValue(0).ToString());
}
// JArray array = JArray...
}
After that I am trying to change the value of filed1 for each object inside the Json Array
JArray array = JArray.Parse(jsonResult.ToString());
foreach (JObject obj in array.Children<JObject>())
{
foreach (JProperty singleProp in obj.Properties())
{
string name = singleProp.Name;
string value = singleProp.Value.ToString();
if(name.ToString() == "field1")
{
Int64 newID = 1234;
value = newID.ToString();
}
}
}
This is working but My BIG QUESTION is how can I get it changed inside the jsonResult?
You simply have to replace the value that you want to update. Since StringBuilder has a .Replace inbuilt method, you can implement that method.
`JArray arr = JArray.Parse(jsonResult.ToString());
foreach (JObject obj in arr.Children<JObject>())
{
foreach(JProperty singleProp in obj.Properties())
{
string name = singleProp.Name;
string value = singleProp.Value.ToString();
if (name.ToString().Equals("field1")) //good practice
{
Int64 newID = 1234;
jsonResult.Replace(value, newID.ToString());//replacing old value with new value and directly updates jsonResult
}
//not necesssary, explanation is given below
var jsonElement = JsonSerializer.Deserialize<JsonElement>(jsonResult.ToString());
result = JsonSerializer.Serialize(jsonElement, options);
}
}`
And for better formatting, I used JsonSerializer so that your output will look like json object rather than whole string without any lines.
` var options = new JsonSerializerOptions()
{
WriteIndented = true
};
var result = ""
while loop{
jsonResult.Append(r.GetValue(0).ToString());
(Above code)
}
`
I have code that gets data from JSON:
dynamic myJSON = Newtonsoft.Json.JsonConvert.DeserializeObject(sourceString);
foreach (var item in myJSON["data"]["results"])
{ ... }
Now, I'd like to make this part myJSON["data"]["results"] for versatile, ideally by passing in a variable such as:
dynamic myJSON = Newtonsoft.Json.JsonConvert.DeserializeObject(sourceString);
var variableResults = ((Newtonsoft.Json.Linq.JArray) string.Format("myJSON[\"{0}\"][\"{1}\"]", myData, myResults);
foreach (var item in variableResults)
{ ... }
I've tried different conversions, and looked here, but no question comes close, and the conversions always comes out string, not a JArray. Any ideas?
You can use JObject to parse it:
var json = "{asd: {qwe: [1,2,3,4]}}";
var obj = JObject.Parse(json);
// just plug in your variables here
var myData = "asd";
var myResult = "qwe";
var path = $"{myData}.{myResult}";
foreach (var item in obj.SelectToken(path).ToObject<int[]>())
{
// ...
}
My solution ended up being:
// User would use a textbox with space separated values like "data results"
var parameterList = textBox1.Text.Trim().Replace(" ", ".");
var jsonObject = JObject.Parse(sourceString);
var jsonList = jsonObject.SelectToken(parameterList);
if (jsonList == null) { ... }
foreach (var item in jsonList)
{ ... }
I am pulling some data from a BigQuery table using the code below in C#
BigQueryClient client = BigQueryClient.Create("<Project Name>");
BigQueryTable table = client.GetTable("<Database>", "Students");
string sql = $"select * FROM {table} where Marks='50'";
BigQueryResults results = client.ExecuteQuery(sql);
foreach (BigQueryRow row in results.GetRows())
{
}
I want to be able to either read the entire results variable into JSON or be able to get the JSON out of each row.
Of course, I could create a class that models the table. And inside the foreach loop, I could just read each row into the class object. The class object I can try to serialize into JSON using a third party like "newton soft".
Something like :
class Student{
int id; // assume these are columns in the db
string name;
}
My foreach would now look like:
foreach (BigQueryRow row in results.GetRows())
{
Student s=new Student();
s.id = Convert.ToString(row["id"]);
s.name= Convert.ToString(row["name"]);
// something like string x=x+ s.toJSON(); //using newton soft
}
This way string x will have the JSON generated and appended for each row.
Or is there a way I can just add each student to a collection or List and then get the JSON from the whole list?
This whole reading row by row and field by field seems tedious to me and there must be a simpler way I feel. Did not see any support from Google BigQuery for C# to directly convert to JSON. They did have something in Python.
If not then the list to JSON would be better but I am not sure if it supported.
Update :
https://github.com/GoogleCloudPlatform/google-cloud-dotnet/blob/master/apis/Google.Cloud.BigQuery.V2/Google.Cloud.BigQuery.V2/BigQueryRow.cs
Looks like the Big Query Row class has a RawRow field which is of Type TableRow. And the class uses JSON references so , I am sure they have the data of the row in JSON format . How can I expose it to me ?
This might be a little late but you can use:
var latestResult = _bigQueryClient.ExecuteQuery($"SELECT TO_JSON_STRING(t) FROM `{ProjectId}.{DatasetId}.{TableName}` as t", null
All columns will be serialized as json and placed in the first column on each row. You can then use something like Newtonsoft to parse each row easily.
I ran into the same issue.
I am posting this solution which is not optimized for performance but very simple for multiple data types.
This allows you to deserialize anything (almost)
public class BQ
{
private string projectId = "YOUR_PROJECT_ID";
public BQ()
{
}
public List<T> Execute<T>(string sql)
{
var client = BigQueryClient.Create(projectId);
List<T> result = new List<T>();
try
{
string query = sql;
BigQueryResults results = client.ExecuteQuery(query, parameters: null);
List<string> fields = new List<string>();
foreach (var col in results.Schema.Fields)
{
fields.Add(col.Name);
}
Dictionary<string, object> rowoDict;
foreach (var row in results)
{
rowoDict = new Dictionary<string, object>();
foreach (var col in fields)
{
rowoDict.Add(col, row[col]);
}
string json = Newtonsoft.Json.JsonConvert.SerializeObject(rowoDict);
T o = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
result.Add(o);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
client.Dispose();
Console.WriteLine("Done.");
}
return result;
}
}
You can use Newtonsoft.Json. First download by PackageManager Console the Nuget Package, here you can get the command to do that.
After download you can use it as the following code:
List<Student> list = new List<Student>();
foreach (BigQueryRow row in results.GetRows())
{
Student s=new Student();
s.id = Convert.ToString(row["id"]);
s.name= Convert.ToString(row["name"]);
list.Add(s);
}
var jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(list);
I hope this can help you.
Here is the complete solution for casting BigQueryResults or GetQueryResultsResponse or QueryResponse data to Model/JSON format using C# reflection:
public List<T> GetBQAsModel<T>(string query) where T : class, new()
{
var bqClient = GetBigqueryClient();
var res = bqClient.ExecuteQuery(query, parameters: null);
return GetModels<T>(res);
}
private List<T> GetModels<T>(BigQueryResults tableRows) where T : class, new()
{
var lst = new List<T>();
foreach (var item in tableRows)
{
var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
var newObject = new T();
for (var i = 0; i < item.RawRow.F.Count; i++)
{
var name = item.Schema.Fields[i].Name;
PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
if (prop == null)
{
continue;
}
var val = item.RawRow.F[i].V;
prop.SetValue(newObject, Convert.ChangeType(val, prop.PropertyType), null);
}
lst.Add(newObject);
}
return lst;
}
private List<T> GetModels<T>(GetQueryResultsResponse getQueryResultsResponse) where T : class, new()
{
var lst = new List<T>();
foreach (var item in getQueryResultsResponse.Rows)
{
var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
var newObject = new T();
for (var i = 0; i < item.F.Count; i++)
{
var name = getQueryResultsResponse.Schema.Fields[i].Name;
PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
if (prop == null)
{
continue;
}
var val = item.F[i].V;
prop.SetValue(newObject, Convert.ChangeType(val, prop.PropertyType), null);
}
lst.Add(newObject);
}
return lst;
}
private List<T> GetModels<T>(QueryResponse queryResponse) where T : class, new()
{
var lst = new List<T>();
foreach (var item in queryResponse.Rows)
{
var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
var newObject = new T();
for (var i = 0; i < item.F.Count; i++)
{
var name = queryResponse.Schema.Fields[i].Name;
PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
if (prop == null)
{
continue;
}
var val = item.F[i].V;
prop.SetValue(newObject, Convert.ChangeType(val, prop.PropertyType), null);
}
lst.Add(newObject);
}
return lst;
}
I would do something like this:
var res = Result. Getrows. Select(x=> new student(){id=x[`ID']}).
And then:
var js = json. Conver(res);
This way is much faster and clearer.
I have below json in string as parameter to a WebMethod.
How can I deserialize in such a way that value comes in Key value pair.
Json String Parameter:
["Ref No,0","Date,0","Amt,0","Sender Name,0","Sender Add,0","Beneficiary Name,0","Beneficiary Add,0","Phone,0","Secret Code,0","Secret Ans,0","Preferred Id,0"]
WebMethod:
[System.Web.Services.WebMethod]
public static string SaveMappings(string mappingData)
{
//string str = "{\"Arg1\":\"Arg1Value\",\"Arg2\":\"Arg2Value\"}";
//JavaScriptSerializer serializer = new JavaScriptSerializer();
//object obj;
//var data = serializer.Deserialize(mappingData,);
var data = mappingData.ToArray();
if (data != null)
{
}
var d2 = mappingData.Split(',');
if (d2!=null)
{
}
return mappingData;
}
If you need to work with JSON data then use Newtonsoft.JSON library.
Convert the object to an array of strings and then split every line.
With this approach you can be sure that the given string is actually an JSON array and it is correct.
var str = "[\"Ref No,0\",\"Date,0\",\"Amt,0\",\"Sender Name,0\",\"Sender Add,0\",\"Beneficiary Name,0\",\"Beneficiary Add,0\",\"Phone,0\",\"Secret Code,0\",\"Secret Ans,0\",\"Preferred Id,0\"]";
string[] objs = JsonConvert.DeserializeObject<string[]>(str);
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (var obj in objs)
{
var keyValue = obj.Split(',');
dic.Add(keyValue[0], keyValue[1]);
}
foreach (var record in dic)
{
Console.WriteLine("{0} => {1}", record.Key, record.Value);
}
Or this one using LINQ. It looks better and it can be written faster. However, it is less optimal (two calls of Split instead of one).
public Dictionary<string, string> FromJsonArray(string jsonArray)
{
return JsonConvert.DeserializeObject<string[]>(jsonArray)
.ToDictionary(obj => obj.Split(',')[0], obj => obj.Split(',')[1]);
}
// ...
var str = "[\"Ref No,0\",\"Date,0\",\"Amt,0\",\"Sender Name,0\",\"Sender Add,0\",\"Beneficiary Name,0\",\"Beneficiary Add,0\",\"Phone,0\",\"Secret Code,0\",\"Secret Ans,0\",\"Preferred Id,0\"]";
foreach (var record in FromJsonArray(str))
{
Console.WriteLine("{0} => {1}", record.Key, record.Value);
}
why don't you just change every ',' in the string array to ':' then pass it to the method, from what you wrote in the question, this should work
I'd like to convert the JSON string
"{ \"birthday\": \"1988-03-18\", \"address\": { \"state\": 24, \"city\": 8341, \"country\": 1 } }"
to
"{ \"address\": { \"city\": 8341, \"country\": 1, \"state\": 24 }, \"birthday\": \"1988-03-18\" }"
NOTE: I'm not using the sorted version for communication (because the key order doesn't really matter), I need a sorted version to perform local tests (by comparing JSON strings).
EDIT: I4V pointed a solution that uses Json.Net, I would rather use a solution that doesn't need to include any 3rd party library (actually I'm using the built in System.Json in my application)
I posted a gist with the solution provided by I4V + some testing here. Thank you all.
I will use Json.Net for this
string json = #"{ ""birthday"": ""1988-03-18"", ""address"": { ""state"": 24, ""city"": 8341, ""country"": 1 } }";
var jObj = (JObject)JsonConvert.DeserializeObject(json);
Sort(jObj);
string newJson = jObj.ToString();
void Sort(JObject jObj)
{
var props = jObj.Properties().ToList();
foreach (var prop in props)
{
prop.Remove();
}
foreach (var prop in props.OrderBy(p=>p.Name))
{
jObj.Add(prop);
if(prop.Value is JObject)
Sort((JObject)prop.Value);
}
}
EDIT
A try with System.Json but I am not sure about OrderByDescending ( or OrderBy).
var jObj = (System.Json.JsonObject)System.Json.JsonObject.Parse(json);
Sort2(jObj);
var newJson = jObj.ToString();
void Sort2(System.Json.JsonObject jObj)
{
var props = jObj.ToList();
foreach (var prop in props)
{
jObj.Remove(prop.Key);
}
foreach (var prop in props.OrderByDescending(p => p.Key))
{
jObj.Add(prop);
if (prop.Value is System.Json.JsonObject)
Sort2((System.Json.JsonObject)prop.Value);
}
}
I know this may be a little late but, in case of you need to sort the internal arrays of data too (I just needed it):
static void Sort(JObject jObj)
{
var props = jObj.Properties().ToList();
foreach (var prop in props)
{
prop.Remove();
}
foreach (var prop in props.OrderBy(p => p.Name))
{
jObj.Add(prop);
if (prop.Value is JObject)
Sort((JObject)prop.Value);
if (prop.Value is JArray)
{
Int32 iCount = prop.Value.Count();
for (Int32 iIterator = 0; iIterator < iCount; iIterator++)
if (prop.Value[iIterator] is JObject)
Sort((JObject)prop.Value[iIterator]);
}
}
}
Cheers!
By using this approach you can retrieve a dynamic object with your json data
At the DynamicJsonConverter create a SortedDictionary instead
var d = new SortedDictionary<string, object>(dictionary);
// TODO: code to sort inner objects
return new DynamicJsonObject(d);
Then you can use
string jsonStr = "{\"B\":\"2\",\"A\":\"1\"}";
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });
dynamic json = jss.Deserialize(jsonStr, typeof(object)) as dynamic;
string result = new JavaScriptSerializer().Serialize((json as DynamicJsonObject).Dictionary);
And result will have the expected output.