i have json string as
{"AccountNo":"345234533466","AuthValue":"{\"TopUpMobileNumber\":\"345234533466\",\"VoucherAmount\":\"100\"}"}
to parse this string i have created class as
public class UserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
}
in AuthValue it gives me output as {\"TopUpMobileNumber\":\"345234533466\",\"VoucherAmount\":\"100\"} which is absolutely correct. now i want to modify my class in such way that i want AuthValue in string format as well and in seprate member variable format.
so i modify my class in this way but it gives error
public class UserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
public Auth ????? { get; set; }
}
public class Auth
{
public string TopUpMobileNumber { get; set; }
public string VoucherAmount { get; set; }
}
My requirement is
AuthValue whole json string i required
in another variable i want member wise values
Parsing Logic
UserContext conObj1 = new UserContext();
conObj1 = JsonConvert.DeserializeObject<UserContext>(context);
Note : No modification in json string is allowed.
I'm not very familiar with JsonConvert or Json.NET so I'm not sure what options are available for that. Personally I'd just call the deserializer again immediately afterwards.
UserContext conObj1 = new UserContext();
conObj1 = JsonConvert.DeserializeObject<UserContext>(context);
conObj1.AuthObject = JsonConvert.DeserializeObject<Auth>(conObj1.AuthValue);
You could move this into the class if you wanted and call it directly off the deserialized class.
public class UserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
public Auth AuthObject { get; private set; }
internal UserContext Deserialize()
{
// Serialize the object
this.AuthObject = JsonConvert.DeserializeObject<Auth>(this.AuthValue);
// Return this object for a simple single-line call.
return this;
}
}
// Single object
UserContext conObj1 = new UserContext();
conObj1 = JsonConvert.DeserializeObject<UserContext>(context).Deserialize();
// Enumeration of object (given that this is supported in JsonConvert)
IEnumerable<UserContext> conObjs = JsonConvert.DeserializeObject<IEnumerable<UserContext>(contexts).Select(c => c.Deserialize()).ToList();
Or if you feel self hating you could go as far as doing the deserialization at the time the property is accessed (although I would avoid this at almost all costs due to the numerous issues it can cause).
public class UserContext
{
private Auth m_auth;
public string AccountNo { get; set; }
public string AuthValue { get; set; }
public Auth AuthObject
{
get
{
if (this.m_auth == null)
{
this.m_auth = JsonConvert.DeserializeObject<Auth>(this.AuthValue);
}
return this.m_auth;
}
}
}
I would suggest using two classes - one for the JSON you're actually receiving, and then one for the object model you want to use:
public class JsonUserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
}
public class UserContext
{
public string AccountNo { get; set; }
public Auth AuthValue { get; set; }
}
public class Auth
{
public string TopUpMobileNumber { get; set; }
public string VoucherAmount { get; set; }
}
...
var jsonUserContext = JsonConvert.DeserializeObject<JsonUserContext>(json);
var authJson = jsonUserContext.AuthValue;
var userContext = new UserContext {
AccountNo = jsonUserContext.AccountNo,
AuthValue = JsonConvert.DeserializeObject<JsonUserContext>(authJson);
};
Related
Hey all I am trying to figure out how to go about saving just one value in my JSON class instead of having to write the whole JSON out again with "New". I am using the Newton JSON.Net.
This is my JSON structure:
public class GV
{
public class Data
{
[JsonProperty("pathForNESPosters")]
public static string PathForNESPosters { get; set; }
[JsonProperty("pathForSNESPosters")]
public static string PathForSNESPosters { get; set; }
[JsonProperty("pathForSEGAPosters")]
public static string PathForSEGAPosters { get; set; }
[JsonProperty("pathToNESContent")]
public static string PathToNESContent { get; set; }
[JsonProperty("pathToSNESContent")]
public static string PathToSNESContent { get; set; }
[JsonProperty("pathToSEGAContent")]
public static string PathToSEGAContent { get; set; }
[JsonProperty("lastSavedVolume")]
public static double LastSavedVolume { get; set; }
}
public class Root
{
public Data data { get; set; }
}
And I have no issues with loading that data from a file into my class:
GV.Root myDeserializedClass = JsonConvert.DeserializeObject<GV.Root>(File.ReadAllText(
currentAssemblyPath + String.Format(#"\Resources\{0}", "dataForLinks.json")
));
But I have yet to find anything searching that will let me do one update to an object in the class without wiping it out doing a New statement.
What I am wanting to do is something like the following:
-Load the json into my class object [Done]
-Save a value thats in my class object [stuck here]
GV.pathToNESContent = "new value here";
-Save class object (with the one new value) back to the file for which it came from preserving the other original values. [not here yet]
When I update just that one class object I am wanting to contain the original values for all the other JSON data I read in from the file.
Anyone have a good example of the above you can share?
update
I'd ditch the inner class structure:
namespace GV
{
public class Data
{
[JsonProperty("pathForNESPosters")]
public string PathForNESPosters { get; set; }
[JsonProperty("pathForSNESPosters")]
public string PathForSNESPosters { get; set; }
[JsonProperty("pathForSEGAPosters")]
public string PathForSEGAPosters { get; set; }
[JsonProperty("pathToNESContent")]
public string PathToNESContent { get; set; }
[JsonProperty("pathToSNESContent")]
public string PathToSNESContent { get; set; }
[JsonProperty("pathToSEGAContent")]
public string PathToSEGAContent { get; set; }
[JsonProperty("lastSavedVolume")]
public double LastSavedVolume { get; set; }
}
public class Root
{
public Data Data { get; set; }
}
Deser (use Path.Combine to build paths, not string concat):
var x = JsonConvert.DeserializeObject<GV.Root>(File.ReadAllText(
Path.Combine(currentAssemblyPath, "Resources", "dataForLinks.json"))
));
Edit:
x.Data.PathToNESContent = "...";
and re-ser
I'm trying to fetch Symptoms from an API. I can fetch them already and I'm serializing it inside a class succesfully. The result looks like in image that i share at below:
There are just IDs and Names inside them. The second table from API is like that:
So here my Entity Class;
using System.Collections.Generic;
public class SymptomousInBodySublocations
{
public int ID { get; set; }
public string Name { get; set; }
public bool HasRedFlag { get; set; }
public ICollection<BodyLocations> HealthSymptomLocationIDs { get; set; }
public string ProfName { get; set; }
public List<string> Synonyms { get; set; }
}
And my Serialize Method:
public static List<SymptomousInBodySublocations> SymptomsInBodySublocations()
{
var client = new RestClient("https://priaid-symptom-checker-v1.p.rapidapi.com/symptoms/31/man?format=json&language=en-gb");
var request = new RestRequest(Method.GET);
request.AddHeader("x-rapidapi-host", "priaid-symptom-checker-v1.p.rapidapi.com");
request.AddHeader("x-rapidapi-key", "<api-key>");
List<SymptomousInBodySublocations> SymptomsInBodySublocationsList = new List<SymptomousInBodySublocations>();
var response = client.Execute<List<SymptomousInBodySublocations>>(request);
foreach(SymptomousInBodySublocations variables in response.Data)
{
SymptomsInBodySublocationsList.Add(variables);
}
return SymptomsInBodySublocationsList;
}
And my BodyLocations Class:
public class BodyLocations
{
public int ID { get; set; }
public string Name { get; set; }
}
In this point when i tried to fetch my data inside my List<BodyLocations>() the response.Data is empty. What should i do?
HealthSymptomLocationIDs isn't an object, looking at the response it is an array of integers.
Changing the field to match the response should populate the field with the integer values from the API
public List<int> HealthSymptomLocationIDs { get; set; }
I am able to handle simple JSON serialization and deserialization but this API response seems little complicated, and I am seeking an advice as to what would be ideal approach to tackle this.
I'm trying to call an API for MVC application.
Goal is to map API data to model.
API endpoint is
https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=MyAPIKey
Troubles here are:
JSON data keys have white space in them.
When I tried doing paste special in Visual studio, It gave me a long
list of classes for each date entry separately, because this API
call returns a separate set of information for date.
To solve problem explained in point 1, I used [JsonProperty("1. Information")] in class. And in my code..
public async Task TSI()
{
HttpClient client = new HttpClient();
//Uri uri = new Uri("http://date.jsontest.com/");
Uri uri = new Uri("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=5min&apikey=demo");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
dynamic result = await response.Content.ReadAsAsync<object>();
IEnumerable<dynamic> dObj = JsonConvert.DeserializeObject<dynamic>(result.ToString());
IEnumerable<dynamic> t1 = dObj.FirstOrDefault();
IEnumerable<dynamic> t2 = dObj.LastOrDefault();
dynamic MetaData = t1.FirstOrDefault();
Rootobject ro = new Rootobject();
ro.MetaData = MetaData;
}
PS: I'm relatively new to make API calls and handling them.
I was able to make a call to
date.jsontest.com
and map the API data to model (which I had created using paste special)
//API response
{
"time": "12:53:22 PM",
"milliseconds_since_epoch": 1504875202754,
"date": "09-08-2017"
}
//C# code to map to API data
public class sampleObject
{
public string time { get; set; }
public long milliseconds_since_epoch { get; set; }
public string date { get; set; }
}
My RootObject looks like this:
public class Rootobject
{
[JsonProperty("Meta Data")]
public MetaData MetaData { get; set; }
[JsonProperty("Time Series (1min)")]
public TimeSeries1Min TimeSeries1min { get; set; }
}
public class MetaData
{
[JsonProperty("1. Information")]
public string _1Information { get; set; }
[JsonProperty("2. Symbol")]
public string _2Symbol { get; set; }
[JsonProperty("3. Last Refreshed")]
public string _3LastRefreshed { get; set; }
[JsonProperty("4. Interval")]
public string _4Interval { get; set; }
[JsonProperty("5. Output Size")]
public string _5OutputSize { get; set; }
[JsonProperty("6. Time Zone")]
public string _6TimeZone { get; set; }
}
// I have so many of these sub-classes for dates, which again is an issue
public class TimeSeries1Min
{
public _20170907160000 _20170907160000 { get; set; }
public _20170907155900 _20170907155900 { get; set; }
....
....}
public class _20170907160000
{
public string _1open { get; set; }
public string _2high { get; set; }
public string _3low { get; set; }
public string _4close { get; set; }
public string _5volume { get; set; }
}
public class _20170907155900
{
public string _1open { get; set; }
public string _2high { get; set; }
public string _3low { get; set; }
public string _4close { get; set; }
public string _5volume { get; set; }
}
It is hard to create a model from this json, but you can convert those data to dictionary
var jObj = JObject.Parse(json);
var metadata = jObj["Meta Data"].ToObject<Dictionary<string, string>>();
var timeseries = jObj["Time Series (1min)"].ToObject<Dictionary<string, Dictionary<string, string>>>();
The following code should do what you want
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<Rootobject>(result);
//No idea what you want to do with this line as there is no MetaData property on the root object
obj.MetaData = MetaData;
}
I have two classes with some similar fields, some different, and a form that utilizes two different objects depending on what mode it's in (insert/edit).
Instead of using two different objects and if statements checking the form mode, I'd like to have one struct to be hydrated with either of the two objects fields so I can manipulate one object through the page life-cycle. Then separated the struct back to its respective object for insert/updating the DB.
Example of classes:
public partial class SomeClass
{
public Int32 B {get;set;}
public String C {get;set;}
public Boolean D {get;set;}
}
public class SomeOtherClass
{
public Int32 A {get;set;}
public Int32 B {get;set;}
public String C {get;set;}
}
Update with Solution Example:
public interface IInsertable
{
string SharedName { get; set; }
string SharedID { get; set; }
string editedFieldValue { get; set; }
long GetSuperSecreteInfo();
}
internal class InsertableImplementation : IInsertable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return -1;
}
}
public interface IUpdateable
{
string SharedName { get; set; }
string SharedID { get; set; }
string updatedFieldValue { get; set; }
Guid GenerateStevesMagicGuid();
}
internal class UpdateableImplementation : IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
public static class WonderTwinFactory
{
public static WonderTwins GenerateWonderTwin(IUpdateable updateable, IInsertable insertable)
{
var wt = new WonderTwins();
// who will win?
wt.SharedID = updateable.SharedID;
wt.SharedID = insertable.SharedID;
// you decide?
wt.SharedName = updateable.SharedName;
wt.editedFieldValue = "stuff";
return wt;
}
}
public class WonderTwins : IInsertable, IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return 1;
}
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
class Program
{
static void Main(string[] args)
{
IUpdateable updateable = new UpdateableImplementation();
IInsertable insertable = new InsertableImplementation();
WonderTwins dualImplementatin = WonderTwinFactory.GenerateWonderTwin(updateable, insertable);
IUpdateable newUpdateable = dualImplementatin as IUpdateable;
IInsertable newInsertable = dualImplementatin as IInsertable;
}
}
Have both classes implement an interface that defines the operations common to each, including both the fields that are shared (assuming the view needs to access them) and also a method to actually perform the operation that they represent (insert/edit).
Other way of doing such things is using C# dynamic object and assign properties directly. It may help to avoid any new type or interface and directly utilizing new dynamic object any time, as much as required.
var newObject = new {
objectOfClass1 = x.prop1,
objectOfClass2 = x.prop2
}
I've been reading for hours and still can't figure out how to use this
under my button I have
WebClient wc = new WebClient();
Uri uri = new Uri("url");
string json = wc.DownloadString(uri);
var a = JsonConvert.DeserializeObject<RootObject>(json);
and the classes
public class Shares
{
public int valid { get; set; }
public int invalid { get; set; }
public int id { get; set; }
public int donate_percent { get; set; }
public int is_anonymous { get; set; }
public string username { get; set; }
}
public class Transactions
{
public double Credit { get; set; }
public double Debit_MP { get; set; }
public double Fee { get; set; }
public int TXFee { get; set; }
}
public class Data
{
public string username { get; set; }
public Shares shares { get; set; }
public int hashrate { get; set; }
public string sharerate { get; set; }
public Transactions transactions { get; set; }
}
public class Getuserstatus
{
public string version { get; set; }
public double runtime { get; set; }
public Data data { get; set; }
}
public class RootObject
{
public Getuserstatus getuserstatus { get; set; }
}
I did a messagebox to check the string from the URL and all the data is there but it doesn't put it into the fields when I call them they're all empty
Shares Share = new Shares();
textBox1.Text += "Username: " + Share.username;
edit:
ok I got it working the a.getsuerstatus.data.shares.username is not valid in the api I don't know why jsontocsharp site added it but all the data is there username is actually a.getuserstatus.data.username thank you all for the help or I would have still be trying to call data using Shares Share = new Shares()
The following code:
Shares Share = new Shares();
textBox1.Text += "Username: " + Share.username;
creates a new instance of an object of type Shares which has the username property initialized to an empty string.
There is no connection with the json-formatted text you'd like to parse.
The method that you are using to parse the json string: var a = JsonConvert.DeserializeObject<RootObject>(json); expects to generate an object of type RootObject
You will want to set the Text property of textbox1 equal to the corresponding Shares object that is deserialized into a.
textbox1.Text = a.getUserStatus.data.shares.username;
The problem isn't the deserialization, it's this;
Shares Share = new Shares();
textBox1.Text += "Username: " + Share.username;
which instead needs to be
textBox1.Text += "Username: " + a.getUserStatus.data.username;
a is the object instantiated by json.NET. You need to go through all the indirection to access the value of username, not just allocated a new Share instance and access it's username, the two references point to entirely different objects.