I am trying to print values from a Json string in a gridview with C# using Visual Studio 2017. The problem is that I can't get the specific Value to a single word.
Here is my code:
string link = #"http://alexander.*************/test.php";
string json = new WebClient().DownloadString(link);
JObject jObject = JObject.Parse(json);
I want to print both Values from "Name" in the gridview, but how?
The Names has to put in this Item list:
myItems = (array?);
string test2 = test1.ToString(Formatting.Indented);
ArrayAdapter<string> adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, myItems);
GridviewCoins.Adapter = adapter;
And finally the json string is:
{
"Coins": [[{
"Name": "007",
"Id": "5294",
}], [{
"Name": "1337",
"Id": "20824",
}
There is a couple problems here, first is that your Coins Property is an array of arrays, and that you jsonObject is not complete it should look like :
"{ "Coins": [[{ "Name": "007", "Id": "5294", } ], [{ "Name": "1337", "Id": "20824", }]]}";
That said if this is a copy paste error I would do some thing like:
public IEnumerable<Coin> GetCoins(string json)
{
var jObject = JObject.Parse(json);
var coinPropery = jObject["Coins"] as JArray;
var coins = new List<Coin>();
foreach (var property in coinPropery)
{
var propertyList = JsonConvert.DeserializeObject<List<Coin>>(property.ToString());
coins.AddRange(propertyList);
}
return coins;
}
and the coin object:
public class Coin
{
public int Id { get; set; }
public string Name { get; set; }
}
when then you have a c# object and you can do what ever you want with it.
EDIT:
You can add to gridview by following Click here
Related
I have a json response that I will need to edit before binding to a GridView. I'm using Newtonsoft JSON library. The data binds perfectly to the GridView when "values" are removed from the string. When values is added to the json response I get this error message.
Message=Unexpected JSON token when reading DataTable. Expected StartArray, got StartObject. Path '', line 1, position 1.
How can I remove "values" from jsonResponse before binding to GridView?
<asp:GridView ID="gvJson" runat="server" BackColor="White" BorderColor="#3399ff"
BorderStyle="Dotted" BorderWidth="1px" CellPadding="3" GridLines="Both" AutoGenerateColumns="true"></asp:GridView>
var jsonResponse = "{\"values\":[{\"id\":\"201\",\"name\":\"Zack\"},{\"id\":\"158\",\"name\":\"Kim\"},{\"id\":\"254\",\"name\":\"Scott\"}]}";
DataTable dataTable = JsonConvert.DeserializeObject<DataTable>(jsonResponse);
gvJson.DataSource = dataTable;
gvJson.DataBind();
My JSON:
{
"values": [
{
"id": "201",
"name": "Zack"
},
{
"id": "158",
"name": "Kim"
},
{
"id": "254",
"name": "Scott"
}
]
}
There are a couple of ways to do this..
You could use JObject
var dataTable = JObject
.Parse(jsonResponse)["values"]
.ToObject<DataTable>();
Or as been suggested, fully deserialize the Json to concrete classes and bind the array to control directly
Given
public class Value
{
public string id { get; set; }
public string name { get; set; }
}
public class Root
{
public List<Value> values { get; set; }
}
Usage
var root = JsonConvert.DeserializeObject<Root>(jsonResponse);
// your Data , root.Data
Instead of removing the values from JSON response, you should be able to do something like
var jsonObject = JObject.Parse(jsonResponse);
var dataTable = JsonConvert.DeserializeObject<DataTable>(jsonObject["values"].ToString());
gvJson.DataSource = dataTable;
gvJson.DataBind();
How to fill ObservableCollection using JSON? Now there is only the script itself and the model in the desktop application. I can not understand how to tie it up.
I get it after running the script:
{
"records": [
{
"brand_id": "1",
"brand_name": "Gigabyte"
},
{
"brand_id": "2",
"brand_name": "MSI"
},
{
"brand_id": "3",
"brand_name": "Lenovo"
},
{
"brand_id": "4",
"brand_name": "Dell"
},
{
"brand_id": "5",
"brand_name": "Google"
}
]}
And I have a Model in app:
public class Brands
{
int brand_id;
string brand_name;
public int Brand_id { get => brand_id; set => brand_id = value; }
public string Brand_name { get => brand_name; set => brand_name = value; }
}
And Collection:
public class BrandsCollection
{
private ObservableCollection<Brands> brands;
public ObservableCollection<Brands> Brands { get => brands; set => brands = value; }
}
It is fairly straight forward, especially with packages available to simplify a lot of the work. The Nuget Package System.Net.Http will have the packages you need to create an HttpClient to Get() your JSON from the web. I recommend Newtonsoft.Json to parse JSON into a C# object. And then having the object you just need to set the DataGrid.ItemSource to be an array of objects of any type for it to generate columns.
A simple example:
First you would define a simple object representation of your JSON data.
For instance if you had the following data:
[
{
"Name":"Test",
"Data": ["Item1","Item2"]
},
{
"Name":"Test 2",
"Data": ["Item3","Item4"]
}
]
You would have to create an equivalent C# representation.
Basically this is a List of objects so:
public class OuterObject : List<InnerObject> {}
The inner object is as follows:
public class InnerObject {
public string Name { get; set; }
public List<string> Data { get; set; }
}
Having the objects defined you can do something like:
HttpClient client = new HttpClient { BaseAddress = new Uri("ADDRESS") };
var json = await client.GetAsync("/ENDPOINT");
JsonSerializer serializer = JsonSerializer.CreateDefault();
using (StringReader reader = new StringReader(json))
{
using (JsonTextReader jsonReader = new JsonTextReader(reader))
{
var result = serializer.Deserialize<OuterObject>(jsonReader);
}
}
Then to access the data in your program you can access it like so:
string name = result[0].Name;
Or set it to a DataGrid's ItemSource to have the Data show up magically.
grid1.ItemSource = result;
As long as the result is an array of items it will create a row per item.
You may want to specify which items are shown but that is done by modifying DataGrid.Columns definitions and setting DataGrid.AutogenerateColumns = false
EDIT: With your data and models
//Just a small change to the Collection
public class BrandsCollection {
private ObservableCollection<Brands> _records;
public ObservableCollection<Brands> records { get => _records; set => _records= value; }
}
And to parse the data...
JsonSerializer serializer = JsonSerializer.CreateDefault();
using (StringReader reader = new StringReader(json))
{
using (JsonTextReader jsonReader = new JsonTextReader(reader))
{
var result = serializer.Deserialize<BrandsCollection>(jsonReader);
}
}
You have to remember to either use the same names as the json labels or use Json Attributes. For more info on that you can go to the official Newtonsoft.Json documentation
Say, the existing document in DB is like this:
{
"_id": "1",
"settings": {
"languages": [ "english", "french" ]
}
}
Now I want to update the document to this:
{
"_id": "1",
"settings": {
"languages": [ "korean", "german" ]
}
}
I tired this following code:
var lan = new List<string> { "finish", "russian", "korean" }
collection.UpdateOne(
Builders<MyObject>.Filter.Eq("_id", "1"),
Builders<MyObject>.Update.Set("settings.languages", lan));
But got following exception:
MongoDB.Bson.Serialization.Serializers.EnumerableInterfaceImplementerSerializer2[System.Collections.Generic.List1[System.String],System.String]' cannot be converted to type 'MongoDB.Bson.Serialization.IBsonSerializer`1[System.String]
I also tried using BsonArray to initialize the new languages array:
var bsonArray = new BsonArray
{
"korean",
"german"
};
collection.UpdateOne(
Builders<MyObject>.Filter.Eq("_id", "1"),
Builders<MyObject>.Update.Set("settings.languages", bsonArray));
The update could be executed without error, but the languages in document is changed to:
{
"_id": "1",
"settings": {
"languages": "[korean, german]"
}
}
It becomes "[ xx, xx ]", instead of [ "xx", "xx" ]. It is not what I expected.
You're getting that error message because you're using strongly typed builders on type MyObject which probably looks more or less like below:
public class MyObject
{
public string _id { get; set; }
public Settings settings { get; set; }
}
public class Settings
{
public string[] languages { get; set; }
}
So since you have a strongly typed Builder you are getting an exception because of the type mismatch between List and Array. Two ways to fix that:
Either use .ToArray() on list to get the same type as the one you have in your MyObject:
var lan = new List<string> { "finish", "russian", "korean" };
collection.UpdateOne(
Builders<MyObject2>.Filter.Eq("_id", "1"),
Builders<MyObject2>.Update.Set("settings.languages", lan.ToArray()));
or skip the type validation using BsonDocument class:
var collection = mydb.GetCollection<BsonDocument>("col");
var lan = new List<string> { "finish", "russian", "korean" };
collection.UpdateOne(
Builders<BsonDocument>.Filter.Eq("_id", "1"),
Builders<BsonDocument>.Update.Set("settings.languages", lan));
I have a bunch of API which generates the following 2 kinds of reply in response body:
{ "error": null, "object_type": { /* some object */ } }
{ "error": null, "object_type": [{ /* some object */ }, { /* some object */ }, ...] }
While I have a class corresponding to the object structure, I want to deserialize the API endpoints directly into either an object of the class or a List<class>, without creating some "result" classes to match the response JSON structure. Is this possible?
For example there is 2 API:
/api/getAllCompanies
returns
{ "error": null, "company": [ { "name": "Microsoft", "country": "US" }, { "name": "Apple", "country": "US" } ]
while
/api/getUserCompany
returns
{ "error": null, "company": { "name": "Microsoft", "country": "US" } }
I have a class in code:
public class Company {
string Name { get; set; }
string Country { get; set; }
}
How can I directly deserialize the data into a Company object or a List<Company> without creating a bunch of other class?
(The JSON property name (company) is known so don't need to extract it elsewhere.)
I've been trying to first deserialize the response JSON into an ExpandoObject then copy the properties to an instance of destination class using the code here then convert it using the following code, but this seems not to work with lists.
private static async Task<T> GetApiObject<T>(string api, string extractedObjName) where T: class, new()
{
var retstr = await /* get API response as string */;
dynamic retobj = JsonConvert.DeserializeObject<ExpandoObject>(retstr, new ExpandoObjectConverter());
var ret = new T();
Mapper<T>.Map((ExpandoObject)((IDictionary<string, object>)retobj)[extractedObjName], ret);
return ret;
}
You can use JObejct to extract the information you need before deserialize it into the object.
var str = "{ \"error\": null, \"company\": [{ \"name\": \"Microsoft\", \"country\": \"US\" } ,{ \"name\": \"Apple\", \"country\": \"US\" } ]}";
var temp = JObject.Parse(str).GetValue("company");
var companies = temp.Select(x => x.ToObject<Company>()).ToList();
Same goes for /api/getUserCompany
var str = "{ \"error\": null, \"company\": { \"name\": \"Microsoft\", \"country\": \"US\" } }";
var temp = JObject.Parse(str).GetValue("company");
var company = temp.ToObject<Company>();
How can I deserialize a string in C# that only have values and no name. It looks like this: The problem is that this stream of string does not have name and uses array.
{
"result": {
"14400": [
[
1502985600,
262.18,
262.18,
257,
257,
1096.0131
],
[
1503000000,
257,
261.33,
254.8,
257,
1130.5897
]
],
"14405": [
[
1503014400,
258.03,
261.5,
257.01,
257.01,
520.7805
],
[
1503028800,
258,
260.98,
252.4,
259.56,
298.5658
],
]
]
}
}
Just create a class like
public class Root
{
public Dictionary<int,List<List<double>>> Result { get; set; }
}
and deserialize as
var res = JsonConvert.DeserializeObject<Root>(json);
I see it's an array, you could create a method to parse the class out of given JArray.
The Jason data
public void methpod()
{
string json ="Your jason value "
var factory = new Factory();
var suggest = factory.Create(json);
Console.WriteLine(suggest);
}
Make a class as suggested :
public class Factory
{
public Evan Create(string json)
{
var array = JArray.Parse(json);
string search = array[0].ToString();
string[] terms = array[1].ToArray().Select(item => item.ToString()).ToArray();
return new Evan{Search = search, Terms = terms};
}
}
and another
public class Evan
{
public string Search { get; set; }
public IEnumerable<string> Terms { get; set; }
public override string ToString()
{
return string.Format("Search={0},Terms=[{1}]",
Search, string.Join(",", Terms));
}
}
Tip
If you have JSON that you want to deserialize, and you don't have the class to deserialize it into, Visual Studio 2019 can automatically generate the class you need:
Copy the JSON that you need to deserialize.
Create a class file and delete the template code.
Choose Edit > Paste Special > Paste JSON as Classes.
The result is a class that you can use for your deserialization target