I need to retrieve the name of every product from an API to a listbox in C# (Visual Studio) and I've managed to login sucessfully into the API. I was able to retrieve the data of each product serialized but when I try to deserialize it the result for each product comes like this: 'app1.Form1+Data'. How can I retrieve the name of each product correctly?
Code:
public class Data
{
public int id { get; set; }
public string name { get; set; }
}
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 1; i <= 20; i++)
{
string url = reqlbl.Text;
WebClient c = new WebClient();
String userName = "user";
String passWord = "pass";
string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord));
c.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;
var json = c.DownloadString(url + i.ToString());
Data result = JsonConvert.DeserializeObject<Data>(json);
listBox1.Items.Add(result);
}
}
Note: The variable 'i' represents a product. There are 20 products in total.
Here's an API example of product 1:
{"1":{"id":1,"name":"Product1"}}
The json is basically a dictionary, ie assuming it can return more than 1 product or something similar, or maybe its just lazily built api, who knows
Exmaple
var str = "{\"1\":{\"id\":1,\"name\":\"Product1\"}}";
var dataDict = JsonConvert.DeserializeObject<Dictionary<string, Data>>(str);
foreach (var data in dataDict.Values)
Console.WriteLine(data.id + ", " + data.name);
Output
1, Product1
Demo here
Related
I am trying to build a SqlQuery at runtime and trying to execute the _context.Database.ExecuteSqlCommandAsync() but getting the following error. There are around 620 rows to be inserted with total number of parameter values around 4400. Not sure how to handle this. Can anyone help me how to solve this.
code:
var sqlSb = new StringBuilder();
sqlSb.AppendLine("INSERT INTO [dbo].[UserTag](UserId, TagId, Disabled, Created, CreatedBy, Modified, ModifiedBy)");
sqlSb.AppendLine("VALUES");
var index = 0;
var noOfcolumnsToInsert = 7;
var query = new SqlQuery();
foreach (var userTag in userTags)
{
var countFrom = index * noOfcolumnsToInsert;
index++;
sqlSb.AppendLine($"({{{countFrom}}}, {{{countFrom + 1}}}, {{{countFrom + 2}}}, {{{countFrom + 3}}}, {{{countFrom + 4}}}, {{{countFrom + 5}}}, {{{countFrom + 6}}}){(index < userTags.Count ? "," : "")}");
query.ParameterValues.AddRange(new List<object> { userTag.UserId, userTag.TagId, userTag.Disabled, currentDateTime, sessionUserGuidAsString, currentDateTime, sessionUserGuidAsString });
}
query.Sql = sqlSb.ToString();
await _context.Database.ExecuteSqlCommandAsync(query.Sql, query.ParameterValues.ToArray());
SqlQuery class:
public class SqlQuery
{
public string Sql { get; set; }
public List<object> ParameterValues { get; set; }
public SqlQuery()
{
ParameterValues = new List<object>();
}
}
Error:
The incoming request has too many parameters. The server supports a maximum of 2100 parameters. Reduce the number of parameters and resend the request
I need to write many sample codes for various API's, which demonstrate how to write the code to use those particular REST API's in C# language.
Now for the API's which are HTTP POST calls, a request body is first created as a class object which is then later serialized into a JSON string and passed to the REST Client.
My Requirement is in this part: "Creating the request Body as a class object".
Following example will make the requirement crystal clear:-
Suppose i have the below JSON Data:
{
"workingDays": ["Monday","Wednesday","Friday"],
"employeeInformation": {
"employeeID": "12345",
"name": {
"firstName": "foo",
"lastName": "bar"
}
},
"joiningDate":"23061984"
}
I need to parse the above data and generate the below code (which currently i am writing manually):
// Create Main Request Body Object
var requestBodyObj = new RequestBody();
// Array Case
var workingDaysObj = new List<string>();
workingDaysObj.Add("Monday");
workingDaysObj.Add("Wednesday");
workingDaysObj.Add("Friday");
requestBodyObj.workingDays = workingDaysObj;
// Nested Object Case
var employeeInformationObj = new employeeInformation();
employeeInformationObj.employeeID = "12345";
var nameObj = new name();
nameObj.firstName = "foo";
nameObj.lastName = "bar";
employeeInformationObj.name = nameObj;
requestBodyObj.employeeInformation = employeeInformationObj;
// Simple Name/Value Pair
requestBodyObj.joiningDate = "23061984";
So as per the above example the JSON Data can be in one of the following 2 forms as well (apart from simple name/value pairs):
Array
Nested Object
And both these cases should be handled as shown in the above code.
Note: User will not be provided with a JSON file so i can't write any code which directly reads a JSON file, deserializes it and assigns the values to a class object using (for example) a NewtonSoft function:
// read file into a string and deserialize JSON to a type
Movie movie1 = JsonConvert.DeserializeObject<Movie>(File.ReadAllText(#"c:\movie.json"));
// deserialize JSON directly from a file
using (StreamReader file = File.OpenText(#"c:\movie.json"))
{
JsonSerializer serializer = new JsonSerializer();
Movie movie2 = (Movie)serializer.Deserialize(file, typeof(Movie));
}
I just want a simple "JSON parser and C# Code generator" (Preferably written in C# language itself).
Any suggestions or pointers will be appreciated.
Edit Update
Pascal Case setting for variable names
Json Object names can be mapped to Project model classes
Write the output to text file for easy copy
Updated Code Below:-
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
namespace SampleCodeCreator
{
class Program
{
// Declaring the variables
static string jsonFilePath = #"[Your File Path]";
static string outputFilePath = #"[Your File Path]";
static string jsonData;
static Dictionary<string, string> classMap = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
static void Main(string[] args)
{
// Initializing Class map which is used to map the json object to Project Model Class
InitializeClassMap();
// clear current data in the output file
using (System.IO.StreamWriter file = new System.IO.StreamWriter(outputFilePath, false))
{
file.Write(String.Empty);
}
// read the json data file and store the data in a simple string
using (StreamReader r = new StreamReader(jsonFilePath))
{
jsonData = r.ReadToEnd();
}
// Call the method for the whole json data
PrintJsonObject("RequestBody", jsonData);
}
static void PrintJsonObject(string parentObject, string jsonData)
{
// if the parent object has any mapped class, then set the object name
parentObject = MappedClass(parentObject);
Console.WriteLine("var {0}Obj = new {1}();", ToCamelCase(parentObject), parentObject);
SetOutput("var " + ToCamelCase(parentObject) + "Obj = new " + parentObject + "();");
Console.WriteLine("");
SetOutput("");
// Deserialize the Json data and iterate through each of its sub-sections
var jsonSubData = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonData);
foreach (var data in jsonSubData)
{
var dataKey = data.Key;
var dataValue = data.Value;
// array case (if the sub element is an array)
if (dataValue.ToString().Contains("["))
{
PrintArrayCase(dataKey, dataValue);
Console.WriteLine("{0}Obj.{1} = {1}Obj;", ToCamelCase(parentObject), dataKey);
SetOutput(ToCamelCase(parentObject) + "Obj." + dataKey + " = " + dataKey + "Obj;");
Console.WriteLine("");
SetOutput("");
}
// nested object case (if the sub element itself contains another json format body)
else if (dataValue.ToString().Contains("{"))
{
// Recursive Call
PrintJsonObject(dataKey, dataValue.ToString());
Console.WriteLine("{0}Obj.{1} = {1}Obj;", ToCamelCase(parentObject), dataKey);
SetOutput(ToCamelCase(parentObject) + "Obj." + dataKey + " = " + dataKey + "Obj;");
Console.WriteLine("");
SetOutput("");
}
// simple key value pair case
else
{
PrintKeyValuePairCase(parentObject, dataKey, dataValue.ToString());
}
}
}
static void PrintArrayCase(string key, object obj)
{
Console.WriteLine("var {0}Obj = new List<string>();", key);
SetOutput("var " + key + "Obj = new List<string>();");
// The array value is split into its values
// e.g. [abc, def, ghi] -> [abc] [def] [ghi]
var valueString = obj.ToString();
var valueSplitArray = valueString.Split(',');
for (int k = 0; k < valueSplitArray.Count(); k++)
{
string listValue = "";
if (k != valueSplitArray.Count() - 1)
{
var startIndex = valueSplitArray[k].IndexOf("\"");
listValue = valueSplitArray[k].Substring(startIndex + 1, valueSplitArray[k].Length - startIndex - 2);
}
else
{
var startIndex = valueSplitArray[k].IndexOf("\"");
listValue = valueSplitArray[k].Substring(startIndex + 1, valueSplitArray[k].Length - startIndex - 5);
}
// each value is then added to the main list object
Console.WriteLine(#"{0}Obj.Add(""{1}"");", ToCamelCase(key), listValue);
SetOutput(#""+ToCamelCase(key)+#"Obj.Add("""+listValue+#""");");
}
Console.WriteLine("");
SetOutput("");
}
static void PrintKeyValuePairCase(string parentObj, string key, string value)
{
Console.WriteLine("{0}Obj.{1} = \"{2}\";", ToCamelCase(parentObj), key, value);
SetOutput("" + ToCamelCase(parentObj) + "Obj." + key + " = \"" + value + "\";");
}
static string ToCamelCase(string str)
{
if (!String.IsNullOrEmpty(str))
{
return str.Substring(0, 1).ToLower() + str.Substring(1, str.Length - 1);
}
else
{
return null;
}
}
static string MappedClass(string str)
{
if (classMap.ContainsKey(str))
return classMap[str];
else
return str;
}
static void InitializeClassMap()
{
classMap.Add("employeeInformation", "EmployeeInfo");
}
static void SetOutput(string str)
{
using (System.IO.StreamWriter file = new System.IO.StreamWriter(outputFilePath, true))
{
file.WriteLine(str);
}
}
}
}
Currently facing an issue when making a JSON string in C# and trying to send it through to a web API using the WebClient.
Currently I have a few methods, first off the one that works. Using POSTMAN sending the following dataset of text through to the API works correctly:
POSTMAN Dataset - This Works in POSTMAN
{ "record":
{
"form_id": "efe4f66f-b57c-4497-a370-25c0f3d8746a",
"status": "240",
"latitude": -82.638039,
"longitude": 27.770787,
"form_values":
{
"833b": "99999",
"683b": "9999999",
"fa37": "Testing",
"b2e3": "Testing"
}
}
}
In C# I am using a few different ways to construct this sting with little success.
C# List Method - Newtonsoft.Json.Serialization
The first is building a List and then using Newtonsoft.Json to play with it:
List<Parent> DataList = new List<Parent>();
List<Child> Form = new List<Child.formvalues>();
var Formvals = new Child.formvalues
{
ActionDescription = Row.ActionDescription,
ActionNotes = Row.ActionNotes,
ActionID = Row.ActionID,
AssetID = Row.AssetID
};
Form.Add(Formvals);
var DataElement = new Parent
{
form_id = AppFormID,
latitude = Lat,
longitude = Long,
status = Row.Status,
form_values = Form
};
DataList.Add(DataElement);
string json = JsonConvert.SerializeObject(DataList.ToArray());
This code results in the following string:
[
{\"form_id\":\"efe4f66f-b57c-4497-a370-25c0f3d8746a\",
\"latitude\":-82.638039,
\"longitude\":27.770787,
\"status\":239,
\"form_values\":[
{\"833b\":99999,
\"683b\":9999999,
\"fa37\":\"Testing\",
\"b2e3\":\"Testing\"
}]
}
]
Another attempt I am trying is the following, which in my opinion is the closest so far:
C# - String Building Method
string Content = #"{ "
+ "\"record\": {"
+ "\"form_id\": "\"" + AppFormID + ""\","
+ "\"status\": "\"" + Row.Status + ""\","
+ "\"latitude\": "+ Lat + ","
+ "\"longitude\": "+ Long + ","
+ "\"form_values\": {"
+ "\"833b\": "\""+Row.AssetID +""\","
+ "\"683b\": "\""+Row.ActionID + ""\","
+ "\"fa37\": "\""+Row.ActionDescription + ""\","
+ "\"b2e3\": "\""+Row.ActionNotes + ""\""
+ "}"
+ "}"
+ "}";
That line results in:
{ \"record\":
{
\"form_id\": \"efe4f66f-b57c-4497-a370-25c0f3d8746a\",
\"status\": \"239\",
\"latitude\": -82.638039,
\"longitude\": 27.770787,
\"form_values\":
{
\"833b\": \"99999\",
\"683b\": \"9999999\",
\"fa37\": \"Testing\",
\"b2e3\": \"Testing\"
}
}
}
The Question!
So the question, is someone able to help me achieving the format in the first JSON that I put into POSTMAN exactly?
UPDATE - 6:40PM
Web client code c#
AppURLRef is set in code further up and appears to be correct in the debugger. json is the result of the tests.
var http = new WebClient();
http.Headers.Add(HttpRequestHeader.ContentType, "application/json");
var response = http.UploadString(AppURLRef, "POST", json);
Result of Update
"[{\"record\":{\"form_id\":\"efe4f66f-b57c-4497-a370-25c0f3d8746a\",
\"latitude\":-82.638039,
\"longitude\":27.770787,
\"status\":\"240\",
\"form_values\":
[{\"833b\":\"99999\",
\"683b\":\"9999999\",
\"fa37\":\"Testing\",
\"b2e3\":\"Testing\"}]}}]"
Try the following.
public class Record
{
[JsonProperty(PropertyName = "form_id")]
public string FormId { get; set; }
[JsonProperty(PropertyName = "status")]
public string Status { get; set; }
[JsonProperty(PropertyName = "latitude")]
public decimal Latitude { get; set; }
[JsonProperty(PropertyName = "longitude")]
public decimal Longitude { get; set; }
[JsonProperty(PropertyName = "form_values")]
public Dictionary<string, string> FormValues { get; set; }
}
public class RecordContainer
{
[JsonProperty(PropertyName = "record")]
public Record Record { get; set; }
}
Usage:
var container = new RecordContainer();
container.Record = new Record();
// Code to populate values
JsonConvert.SerializeObject(container);
I am using Newtonsoft Json to serialize and I get the same output that you have asked for.
I'd try the following along with NewtonSoft.JSON.
var data = new
{
record = new
{
form_id = "efe4f66f-b57c-4497-a370-25c0f3d8746a",
status = "240",
latitude = -82.638039,
longitude = 27.770787,
form_values = new Dictionary<string, string>();
}
}
data.record.form_values["833b"] = "99999";
data.record.form_values["683b"] = "9999999";
data.record.form_values["fa37"] = "Testing";
data.record.form_values["b2e3"] = "Testing";
Then get the JSON:
string json = JsonConvert.SerializeObject(data);
I think it is much similar to this One. you can try the following code to achhieve the requirement:
var dd = {
"FirstName": "ABC",
"username": "abc123",
"password": "abc#123",
"Cnumbers": [{
"Home": "0987654321"
}, {
"Company": "7654321"
}]
}
In C# I make a GET reqeust to get som JSON data. In this JSON data there is an array, which I want to return the elements in this data. I'm using Json.NET to try to achieve this.
Here is my C# code to get a property in the JSON file.
public static string sendRequest(string url, string method)
{
try
{
// Set reqiued information for api
var httpWebRequest = (HttpWebRequest)WebRequest.Create(main_url + url);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Headers.Add("Authorization", "Bearer " + Current_Access_Token);
httpWebRequest.Accept = "application/json;v=1";
httpWebRequest.Method = method;
// Get adn return responses
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
string respStr = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
return respStr;
}
catch (Exception e)
{
MessageBox.Show("No response");
}
return "";
}
public static string GetUserName()
{
string resp = sendRequest("api.php/currentCustomer/", "GET");
JObject jObject = JObject.Parse(resp);
JToken Juser = jObject["response"];
string UserName = (string)Juser["data"]["customer"]["name"];
return UserName;
}
The code above is how I return the name of a customer under customer. But under customer there is an array, "active_digital_subscriptions". In this array there is 2 elements which I want to access and save in setting.setting. "active_digital_subscriptions" only contains string.
JSON data:
{
"response":{
"code":200,
"status":"success",
"data":{
"customer":{
"id":"109701",
"email":"ahjune152#one.com",
"name":"ahjune152",
"first_name":"Loc",
"last_name":"Dai Le",
"registration_date":"2015-06-17",
"last_login_date":"2015-11-05",
"is_newsletter_subscriber":"1",
"digital_password":"YOtI1cuzL18dO3i9T9CBVCiX3lQa3iIPhcWDgiwHxxI=",
"language":{
"id":"1",
"name":"American english",
"code":"en"
},
"currency":{
"id":"1",
"name":"Danske kroner",
"sign":"DKK",
"code":"DKK",
"number":"208"
},
"preferred_platforms":[
],
"active_digital_subscriptions":[
{
"plan_id":"246",
"plan_title":"VIP Partner"
}
]
}
}
}
}
You can use SelectToken and SelectTokens for this purpose. Both support JSONPath query syntax:
var userName = (string)Juser.SelectToken("data.customer.name");
var customersItems = Juser.SelectTokens("data.customer.customers_items[*]")
.Select(t => (string)t)
.ToArray();
[*] is a wildcard that selects all elements in the array.
Update
Given your revised JSON, you can get the active user and active subscriptions like so:
var userName = (string)Juser.SelectToken("data.customer.name");
var activeSubscriptions = Juser.SelectTokens("data.customer.active_digital_subscriptions[*]")
.Select(t => new { PlanId = (string)t["plan_id"], PlanTitle = (string)t["plan_title"] })
.ToArray();
Note that the active subscriptions are in an array, so it would appear possible that there could be more than one. If you know there is only one, you can do
var activeSubscription = activeSubscriptions.SingleOrDefault();
Here I am returning the subscriptions in an anonymous type but you could define an explicit class if you prefer:
public class Subscription
{
public string PlanId { get; set; }
public string PlanTitle { get; set; }
}
And then do:
var activeSubscriptions = Juser.SelectTokens("data.customer.active_digital_subscriptions[*]")
.Select(t => new Subscription { PlanId = (string)t["plan_id"], PlanTitle = (string)t["plan_title"] })
.ToArray();
You could try this -
var subs = (JArray)JObject.Parse(json)["response"]["data"]["customer"]["active_digital_subscriptions"];
for (var i = 0; i < subs.Count; ++i)
{
var id = ((JValue)subs[i]["plan_id"]).Value;
var title = ((JValue)subs[i]["plan_title"]).Value;
}
im reprogramming the tf2 tradebot by JesseCar 96 for CS:go. Im trying to get the items stored in a list array and I can't figure out how to access it. The instantiation and item data works like this:
public class TradeUserAssets : IEquatable<TradeUserAssets>, IComparable<TradeUserAssets>
{
/// <summary>Inventory type</summary>
public long contextid { get; private set; }
/// <summary>itemid</summary>
public ulong assetid { get; private set; }
public int appid { get; private set; }
public int amount { get; private set; }
public TradeUserAssets(int appid, long contextid, ulong assetid, int amount = 1)
{
this.appid = appid;
this.contextid = contextid;
this.assetid = assetid;
this.amount = amount;
}}
It is instantiated through:
private List<TradeUserAssets> otherOfferedItems;
otherOfferedItems = new List<TradeUserAssets>();
But when I use this foreach loop to get the data
foreach (long contextid in Trade.OtherOfferedItems.ToString())
{
Console.WriteLine(contextid);
}
The bot crashes. I've tried using a for loop and using the index number after .ToString()[i] like this but I can't get any of the data out. If I do anything other than .ToString() after OtherOfferedItems it won't build. Any help is really appreciated!
EDIT: This is my userHandler.cs
string tradeid;
if (myItems.Count == 0)
{
offer.Accept(out tradeid);
Log.Success("Accepted trade offer successfully : Trade ID: " + tradeid);
foreach (asset in Trade.OtherOfferedItems)
{
Console.WriteLine(asset);
}
using (var connection = new MySqlConnection("Server=localhost;Database=skindump;Uid=USERNAME;Pwd=PASSWORD;"))
{
var time = DateTime.Now.TimeOfDay;
var date = DateTime.Now;
date.ToString();
connection.Open();
MySqlCommand cmd = new MySqlCommand("INSERT INTO trades (tradeID, tradeUsed, tradeDate, steamID) VALUES (" + tradeid + ", 1, '" + date + "', '" + OtherSID.ConvertToUInt64() + "');");
cmd.Connection = connection;
cmd.ExecuteNonQuery();
Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
Console.WriteLine(date);
connection.Close();
}
}
Line 201 is the open squiggly bracket after the mysql connection (var connection = new mysql connection etc...). When I comment out the foreach loop it runs fine without crashing so thats definitely the issue.
You probably want to access a property inside of each object of your list. But what you are doing is just converting the Trade.OtherOfferedItems list to a string and then looping over that. You probably want to do something like this instead:
foreach (TradeUserAssets asset in Tade.OtherOfferedItems)
{
Console.WriteLine(asset.contextid);
}
You're trying to access the contextid by using ToString(), which is the wrong way to do it.
Instead, iterate through the collection of TradeUserAssets, and access the property inside the loop.
foreach (var asset in Trade.OtherOfferedItems)
{
Console.WriteLine(asset.contextid);
}
The reason your current code compiles is because it's returning the ascii value for each character in the string that ToString() returns (which is just the class name of the collection). Even if it didn't crash the app at runtime, it wouldn't be what you want.