I'm trying to loop over a JSON string in my Android app. This is the code I have so far, using answers I found on line.
private void updateAutoComplete() {
var testJSON = "{result:[{\"symbol\":\"FB\",\"typeDisp\":\"Equity\",\"exchDisp\":\"NASDAQ\",\"exch\":\"NAS\",\"name\":\"Facebook, Inc.\",\"type\":\"S\"},{\"symbol\":\"FB2A.DE\",\"typeDisp\":\"Equity\",\"exchDisp\":\"XETRA\",\"exch\":\"GER\",\"name\":\"Facebook, Inc.\",\"type\":\"S\"}]}";
var autoCompleteOptions = getAutoCompleteOptions (testJSON);
ArrayAdapter autoCompleteAdapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleDropDownItem1Line, autoCompleteOptions);
var autocompleteTextView = FindViewById<AutoCompleteTextView>(Resource.Id.AutoCompleteInput);
autocompleteTextView.Adapter = autoCompleteAdapter;
}
private String[] getAutoCompleteOptions(String json) {
var autoCompleteOptions = new String[20];
int i = 0;
dynamic dynObj = JsonConvert.DeserializeObject(json);
foreach (var data in dynObj.result) { //x
autoCompleteOptions.SetValue (data.symbol, i);
i++;
}
return autoCompleteOptions;
}
Want I want is to get the different symbols from the JSON in an array so I can use it for the autocomplete.
When I run the app (updateAutoComplete is called in the OnCreate), I get following error: 'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'result' on the line marked with the x.
Anyone know what might be the problem?
Thanks in advance.
If you are trying to go the route of not serializing back into an object you can cherry pick the data out of the string that you need with a JObject.
JObject root = JObject.Parse(testJSON);
var result = (JArray)root["result"];
result.ToList().ForEach(x =>
{
var symbol = x["symbol"];
symbol.Dump();
});
//FB
//FB2A.DE
Related
I am new to programming and been tasked to grab data from an API.
The issue I have is basic C# returning the contents of brakeparts. I'm passing the part id and obtaining a list of brake parts correctly. I need to assign the partid to the list, which seems to work when adding a breakpoint, however how do I return this list? Return brake parts doesn't work. They could be potentially many parts it returns whilst looping I need it to append to the Parts list. I know its probably something quite simple but I can't get my head around returning back the whole list. I've tried brakeparts.AddRange(brakeparts); This doesn't work too.
private static List<Parts> getBrakeparts(List<int> partids)
{
var restClient = new RestClient("https://example.example.net/api");
foreach (var partid in partids)
{
var returnreq = new RestRequest($"/brakeparts/{partid}/ ", Method.GET);
var res = restClient.Execute(returnreq);
Parts brakeparts = JsonConvert.DeserializeObject<Parts>(res.Content);
brakeparts.PartID = partid;
}
return brakeparts;
}
As I understand, you're simply trying to return a list of parts which you want to fill with the Parts breakparts that you deserialized from the Json response.
Simply create a List<Parts> instance and add the breakparts to it in the loop.
It could look like the following.
private static List<Parts> getBrakeparts(List<int> partids)
{
var restClient = new RestClient("https://example.example.net/api");
List<Parts> parts = new List<Parts>();
foreach (var partid in partids)
{
var returnreq = new RestRequest($"/brakeparts/{partid}/ ", Method.GET);
var res = restClient.Execute(returnreq);
Parts brakeparts = JsonConvert.DeserializeObject<Parts>(res.Content);
brakeparts.PartID = partid;
parts.Add(brakeparts);
}
return parts;
}
Please, can you help me create/update items from custom fields that have space within their name?
We have a project with a custom field Contact phone. This field can be used correctly from the browser. https://github.com/Workfront/workfront-api-examples-csharp didn't help. I was able to add the data within the details of the issue. I would like to add it within the specific custom field (create/update).
var client = new AtTaskRestClient(_url); // from the example
...
var description = $"Contact phone: {item.ContactPhone}";
client.Create(ObjCode.ISSUE, new { name = item.Name,
description = description,
projectID = _projectID });
client.Create has an object as final parameter. We use an anonymous type that can't contain "DE:Contact phone" = item.ContactPhone within the constructor. How can we write this field?
Reading DE:Contact phone works correctly if we insert the value from the browser:
JToken issues = client.Search(ObjCode.ISSUE, new { projectID = _projectID });
foreach (var issue in issues["data"].Children()) {
var name = issue.Value<string>("name"); // correct
var id = issue.Value<string>("ID"); // correct
var fields = client.Get(ObjCode.ISSUE, id, new[] { "description", "DE:Contact phone"}); // correct
https://github.com/Workfront/workfront-api-examples-csharp/blob/master/AtTaskRestExample/AtTaskRestClient.cs
public JToken Create(ObjCode objcode, object parameters) {
VerifySignedIn();
string[] p = parameterObjectToStringArray(parameters, "sessionID=" + SessionID);
JToken json = client.DoPost(string.Format("/{0}", objcode), p);
return json;
}
I wrote a new function CreateEx, that receives a string array
public JToken Create(ObjCode objcode, string[] parameters) {
VerifySignedIn();
JToken json = client.DoPost(string.Format("/{0}", objcode), parameters);
return json;
}
It is accessed as follows:
var client = new AtTaskRestClient(_url); // from the example
...
string[] parameteres =
{
$"name={issueName}",
$"description={description}",
$"projectID={_projectID}",
$"sessionID={client.SessionID}",
$"DE:Contact phone={contactPhone}"
};
client.CreateEx(ObjCode.ISSUE, parameteres);
I'm receiving json files of different schema and have to dump them in sql data base.
The json files have the schema
{'type':'abc','data':{'column1':'x','column2':'y',.........}}
Corresponding to each type of schema I have a strongly typed class named similar to the type but with word 'Table' attached..
eg. 'abcTable' which has only the schema of json.data (column1, column2, ...)
So, what I can do is do a dynamic deserializing of the main json and then based on the type value do a strongly typed json parsing of the corresponding data
dynamic jsondata = JsonConvert.DeserializeObject<dynamic>(json);
if (jsonata.type=='abc')
{
var abcobj = JsonConvert.DeserializeObject<abcTable>(jsondata.data);
}
Here I'm deserializing the object twice, so don't look like the right way of doing..
Also I have 25+ such schemas and a similar number of classes/tables
So, I will be using a lot of if / else if /else statements...
I would like to understand if there are other better ways of solving what I'm trying to do..
Any help is sincerely appreciated..
Thanks
As usually, JObject is your friend:
var parsed = JObject.Parse(json);
var type = parsed.Value<string>("type");
if (type == "abc")
{
var abcObject = parsed["data"].ToObject<abcTable>();
}
I order to avoid many ifs, you can use the follwing pattern:
public interface ITableType
{
bool Match(string type);
void Handle(JToken jsonTable);
}
public AbcTableHandler: ITableType
{
public bool Match(string type)
{
return type == "abc";
}
public void Handle(JToken jsonTable)
{
var abcTable = jsonTable.ToObject<abcTable>();
// other code
}
}
usage:
var handlers = new[] { new AbcTableHandler() };
// ...
var parsed = JObject.Parse(json);
var type = parsed.Value<string>("type");
var handler = handlers.SingleOfDefault(h => h.Match(type));
if (handler == null)
throw new InvalidOperationException("Cannot find handler for " + type);
handler.Handle(parsed["data"]);
EDIT:
Adding multiple handlers:
var handlers = new ITableType[] { new AbcTableHandler(), new OtherHandler, etc.. };
or
var handlers = new List<ITableType>();
handlers.Add(new AbcTableHandler());
handlers.Add(new OtherHandler());
Okay so I have a small section of code which creates a list of objects based on the data model. I don't want to have to create a class for this. It is used on n ASP.net MVC application for populating a user notifications list.
I know there are plenty of other ways to do this such as actually setting up a class for it(probably the easiest method), but I would like to know if there is a way to do what is displayed below.
List<object> notificationList = new List<object>();
object userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach(object notification in notificationList)
{
string value = notification.Text;
}
So I haven't populated the list much but for the purposes here you get the idea. After debug I notice that the Text and Url properties exist, however cannot code to get the values???
You need to use dynamic as variable type in the foreach:
foreach(dynamic notification in notificationList)
{
string value = notification.Text;
}
Edit Oops ... you do need "dynamic", either as the List's generic type, or in the foreach.
var notificationList = new List<dynamic>();
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach (var notification in notificationList)
{
string value = notification.Text;
}
End edit
Anonymous types should be declared using the var keyword:
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
You could also use "dynamic" instead of "var", but that deprives you of compile-time checks, and it appears unnecessary in this case (because the type is fully defined at compile time, within the same method scope). A case where you would need to use "dynamic" is where you want to pass the anonymous-typed object as a parameter to another function, eg:
void Func1()
{
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
Func2(userNotification);
}
void Func2(dynamic userNotification)
{
string value = notification.Text;
}
Well you could declare the list as an list of dynimac objects:
List<dynamic> notificationList = new List<object>();
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach(dynamic notification in notificationList)
{
string value = notification.Text;
}
or use var to let the compiler choose the type:
var notificationList = new []
{
new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" }
}.ToList();
foreach(var notification in notificationList)
{
string value = notification.Text;
}
I've successfully deserialized this JSON string in C#, but can't extract the values from the objects nested in the array:
JavaScriptSerializer js = new JavaScriptSerializer();
string json =
{"key":"1234","status":"ok","members":
[{"id":7,"name":"Joe"},
{"id":2,"name":"Robert"},
{"id":18,"name":"Tim"}
]
}
var d = js.Deserialize < dynamic > (json);
string _key = d["key"]; // this works
Array _members = d["members"]; // this works, length = 3
But I'm having trouble extracting the values out of the objects by name, e.g, this isn't right, but essentially I want
_members[0]["name"] or, _members[0].name
I think the deserializer makes the objects inside the array dictionaries, but I think I'm clearing missing something...
I recommend using Json.NET to do what you're doing. The following code does what you want:
JObject jObject = JObject.Parse(json);
JToken memberName = jObject["members"].First["name"];
Console.WriteLine(memberName); // Joe
Via LINQ to Json.
Update:
var js = new JavaScriptSerializer();
var d = js.Deserialize<dynamic>(json);
Console.WriteLine(d["members"][0]["name"]); // Joe
Also works fine.
It's a bit late for an answer but I've been trying to figure this out and thought I should post somewhere what worked for me.
I wanted to use foreach so:
foreach (var member in json["members"])
{
Console.WriteLine(member["name"]);
}
and by the way, (for some reason like in my project) if you have nested arrays, e.g.
string json =
{"key":"1234","status":"ok",
"members":[
{"items"[
{"id":7,"name":"Joe"},
{"id":2,"name":"Robert"},
{"id":18,"name":"Tim"}
]}
]}
Then:
foreach (var member in json["members"])
{
foreach (var item in member["items"])
{
Console.WriteLine(item["name"]);
}
}
You were quite close in syntax. The key here is that d["members"] is of type Object[] / object[]. Instead of Array, you can use dynamic[] and everything works just fine.
Also note that even this declaration isn't explicitly necessary, as shown in DPeden's updated sample.
Here is the code for your updated snippet (I used a console app to test):
JavaScriptSerializer js = new JavaScriptSerializer();
dynamic d = js.Deserialize<dynamic>(json);
string key = d["key"];
string status = d["status"];
dynamic[] members = d["members"];
Console.WriteLine("key = {0}", key);
Console.WriteLine("status = {0}", status);
Console.WriteLine("members.length = {0}", members.Length);
Console.WriteLine("members type name = {0}", members.GetType().Name);
Console.WriteLine("d[\"members\"] type name = {0}", d["members"].GetType().Name);
And here is additional code showing array and member access.
Console.WriteLine("--");
for (int i = 0; i < members.Length; i++)
{
Console.WriteLine("members[{0}][\"id\"] = {1}", i, members[i]["id"]);
Console.WriteLine("members[{0}][\"name\"] = {1}", i, members[i]["name"]);
}
Console.WriteLine("--");
Console.WriteLine("{0}", d["members"][0]["id"]);
Console.WriteLine("{0}", d["members"][0]["name"]);
Console.ReadKey();