Json class saving a value while containing other default values - c#

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

Related

Serializing Response Inside A Class As A List

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; }

Deserialize multiple JSON records in C# [duplicate]

This question already has an answer here:
Deserializing JSON into an object
(1 answer)
Closed 5 years ago.
I have the following string of Json records:
{
"records":[
{
"PK":"1_1_8",
"ID":"8",
"DeviceID":"1",
"RootID":"1",
"CustName":"test1",
"CustSurname":"test2",
"Address":"Nisou 1",
"City":"",
"ZipCode":"",
"PhoneNumber":"45646",
"HomePhoneNumber":"",
"Email":"",
"Notes":"",
"Owner":"1",
"LanguageID":"1",
"LanguagePK":"",
"DeletedFlag":"false",
"created":"2017-10-25 10:15:00",
"modified":"2017-10-25 09:35:43"
},
{
"PK":"1_1_33",
"ID":"33",
"DeviceID":"1",
"RootID":"1",
"CustName":"",
"CustSurname":"",
"Address":"",
"City":"",
"ZipCode":"",
"PhoneNumber":"",
"HomePhoneNumber":"",
"Email":"",
"Notes":"",
"Owner":null,
"LanguageID":"0",
"LanguagePK":"",
"DeletedFlag":"true",
"created":"2017-10-25 10:13:54",
"modified":"2017-10-25 10:13:54"
},
{
"PK":"1_1_16",
"ID":"16",
"DeviceID":"1",
"RootID":"1",
"CustName":"Theodosis",
"CustSurname":"",
"Address":"Dali",
"City":"Nicosia",
"ZipCode":"2540",
"PhoneNumber":"45645",
"HomePhoneNumber":"99123456",
"Email":"theodosis#gmail.com",
"Notes":"",
"Owner":"",
"LanguageID":"1",
"LanguagePK":"",
"DeletedFlag":"false",
"created":"2017-10-25 09:36:22",
"modified":"2017-10-25 09:36:22"
}
]
}
I am using Xamarin PCL in C# trying to parse this string into a list of objects.
I have a Customer class:
public class Customer
{
[PrimaryKey]
public string PK { get; set; }
public int DeviceID { get; set; }
public int ID { get; set; }
public string RootID{ get; set; }
public string CustName { get; set; }
public string CustSurname { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string PhoneNumber { get; set; }
public string HomePhoneNumber { get; set; }
public string Email { get; set; }
public string Notes { get; set; }
public bool Owner { get; set; }
public int LanguageID { get; set; }
public string LanguagePK { get; set; }
public bool DeletedFlag { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
}
I also tried out having a container class with a list of Customer objects.
public class DataContainer
{
public List<Customer> customers { get; set; }
}
I have seen quite a few of examples online on how to parse this into a list or any workable type but nothing seems to be working for me.
I have tried the following (JsonResults holds the string of Json records):
var observation = JsonConvert.DeserializeObject<DataContainer>(JsonResults);
From other posts, I am not able to access JavaScriptSerializer class from my code, perhaps because of the Xamarin PCL Framework I am using.
Any ideas would be very welcome, as I said I do not mind the format I parse the string into, as long as it's workable.
Thank you.
You would have to make the following changes to your code to make this work.
First and most importantly, you don't have a property customers, you have records, so either rename it
public class DataContainer {
public List<Customer> records { get; set; }
}
or add a JsonProperty attribute
[JsonProperty(PropertyName = "records")]
Secondly, your Owner is a bool in C# and a nullable int (int?) in Json. So either change it in your C# class
public int? Owner { get; set; }
or write a converter to do that (e.g. like here)
[JsonConverter(typeof(NullableIntToBooleanConverter))]
public bool Owner { get; set; }
Here is a working .NetFiddle
The JSON string you provided is a JSON object, which contains a single property called records. records property is a List<Customer>. You can not deserialize the given string directly into DataContainer class that you provided because the property names do not match.
In the Class that your provided it is called customers
public class DataContainer {
public List<Customer> customers { get; set; } //records
}
Or please have a look at the attribute for a bit of advanced mapping
[JsonProperty]
JSON you provided is of the form:
{"records":[{Customer},{Customer},{Customer}]}
But Owner property is "1", null or "". Therefore I would suggest redefining Owner as int? (nullable)
Your string shows one object with a property named records that contains a list of other objects. Your code is trying to deserialize this into an object that doesn't have such a property.
Furthermore, the string contains objects with a property Owner that may be missing or have a numeric value. It's definitely not a bool.
You'll have to change Owner to :
public int? Owner { get; set; }
To deserialize the string, you need an object with a records property:
public class DataContainer
{
public Customer[] records { get; set; }
}
var data=JsonConvert.DeserializeObject<DataContainer>(json);
Debug.Assert(data.records.Length == 3);

Deserialise JSON containing numeric key with Json.NET

I would like to deserialize the following JSON (using Json.NET) to an object, but cannot, as the class name would need to begin with a number.
An example of this is the Wikipedia article API. Using the API to provide a JSON response returns something like this. Note the "16689396" inside the "pages" key.
{
"batchcomplete":"",
"continue":{
"grncontinue":"0.893378504602|0.893378998188|35714269|0",
"continue":"grncontinue||"
},
"query":{
"pages":{
"16689396":{
"pageid":16689396,
"ns":0,
"title":"Jalan Juru",
"extract":"<p><b>Jalan Juru</b> (Penang state road <i>P176</i>) is a major road in Penang, Malaysia.</p>\n\n<h2><span id=\"List_of_junctions\">List of junctions</span></h2>\n<p></p>\n<p><br></p>"
}
}
}
}
How could I deserialize this JSON containing a number which changes based on the article?
It sounds like the Pages property in your Query class would just need to be a Dictionary<int, Page> or Dictionary<string, Page>.
Complete example with the JSON you've provided - I've had to guess at some of the name meanings:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
public class Root
{
[JsonProperty("batchcomplete")]
public string BatchComplete { get; set; }
[JsonProperty("continue")]
public Continuation Continuation { get; set; }
[JsonProperty("query")]
public Query Query { get; set; }
}
public class Continuation
{
[JsonProperty("grncontinue")]
public string GrnContinue { get; set; }
[JsonProperty("continue")]
public string Continue { get; set; }
}
public class Query
{
[JsonProperty("pages")]
public Dictionary<int, Page> Pages { get; set; }
}
public class Page
{
[JsonProperty("pageid")]
public int Id { get; set; }
[JsonProperty("ns")]
public int Ns { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("extract")]
public string Extract { get; set; }
}
class Test
{
static void Main()
{
string text = File.ReadAllText("test.json");
var root = JsonConvert.DeserializeObject<Root>(text);
Console.WriteLine(root.Query.Pages[16689396].Title);
}
}
Related question: Json deserialize from wikipedia api with c#
Essentially you need to changes from using a class for the pages to a dictionary, which allows for the dynamic nature of the naming convention.
Class definitions :
public class pageval
{
public int pageid { get; set; }
public int ns { get; set; }
public string title { get; set; }
public string extract { get; set; }
}
public class Query
{
public Dictionary<string, pageval> pages { get; set; }
}
public class Limits
{
public int extracts { get; set; }
}
public class RootObject
{
public string batchcomplete { get; set; }
public Query query { get; set; }
public Limits limits { get; set; }
}
Deserialization :
var root = JsonConvert.DeserializeObject<RootObject>(__YOUR_JSON_HERE__);
var page = responseJson.query.pages["16689396"];
You can implement your own DeSerializer or editing the JSON before you DeSerialize it.

Deserialize CSV string to an C# Object

I have a response from Jira API, require to be deserialized into data model:
com.atlassian.greenhopper.service.sprint.Sprint#40675167[id=10151,rapidViewId=171,state=CLOSED,name=Sprint 37.1,startDate=2015-07-30T16:00:22.000+03:00,endDate=2015-08-13T16:00:00.000+03:00,completeDate=2015-08-13T14:31:34.343+03:00,sequence=10151]
This is actually the information of current sprint for issue.
I need to deserialize it to a model like:
public class Model
{
public string name { get; set; }
...
}
I have already removed all non-required information, like com.atlassian.greenhopper.service.sprint.Sprint#40675167 using Regex pattern \[(.*?)\] so I have brackets and all inside.
Now I stopped completely trying to find the a way to convert this string to a data model.
Found the following thread at the Atlassian Answers page and there appears to be no JSON representation of that inner Object. As shown in the example from that thread:
customfield_10007:[
"com.atlassian.greenhopper.service.sprint.Sprint#a29f07[rapidViewId=<null>,state=CLOSED,name=NORD - Sprint 42,startDate=2013-07-29T06:47:00.000+02:00,endDate=2013-08-11T20:47:00.000+02:00,completeDate=2013-08-14T15:31:33.157+02:00,id=107]",
"com.atlassian.greenhopper.service.sprint.Sprint#769133[rapidViewId=<null>,state=ACTIVE,name=NORD - Sprint 43,startDate=2013-08-14T15:32:47.322+02:00,endDate=2013-08-23T15:32:47.322+02:00,completeDate=<null>,id=117]"
],
The response is indeed a JSON array, but the array itself contains CSV's, so you can make use of the following to parse that:
public class DataObject
{
public string id { get; set; }
public string rapidViewId { get; set; }
public string state { get; set; }
public string name { get; set; }
public string startDate { get; set; }
public string endDate { get; set; }
public string completeDate { get; set; }
public string sequence { get; set; }
}
public class Program
{
private const string sampleStringData =
#"[id=10151,rapidViewId=171,state=CLOSED,name=Sprint 37.1,startDate=2015-07-30T16:00:22.000+03:00,endDate=2015-08-13T16:00:00.000+03:00,completeDate=2015-08-13T14:31:34.343+03:00,sequence=10151]";
static void Main(string[] args)
{
var dataObject = new DataObject();
string[][] splitted;
var sampleWithNoBrackets = sampleStringData.Substring(1,sampleStringData.Length-2);
splitted = sampleWithNoBrackets.Split(',').Select(p => p.Split('=')).ToArray();
dataObject.id = splitted[0][1];
dataObject.rapidViewId = splitted[1][1];
dataObject.state = splitted[2][1];
dataObject.name = splitted[3][1];
dataObject.startDate = splitted[4][1];
dataObject.endDate = splitted[5][1];
dataObject.completeDate = splitted[6][1];
dataObject.sequence = splitted[7][1];
Console.ReadKey();
}
}
Here's the output for the above:

Xml Serialization for list Property doesn't work when one item in the list

<TotalRecords ItineraryCount='1' >
<Recs ItineraryNumber="1" >
<Amount>516.6</Amount>
<TravelTime>940</TravelTime>
<FSegment>
<OutProperty>
<Segment No="1">
<Name>Ronald</Name>
<City>London</City>
<Country>United Kingdom</Country>
</Segment>
<Segment No="2">
<Name>Richard</Name>
<City>
London
</City>
<Country>United Kingdom</Country>
</Segment>
</OutProperty>
</FSegment>
</Recs>
</TotalRecords >
I am serializing xml to object of TotalRecords Class. It works fine when there are more than one segment in the OutProperty but in case of one segment it doesn't serialize into list property.
I have also tried with [XmlArray("")] and [XMlArrayItem("")] but it doesn't work. Anyone have idea?
public class TotalRecords
{
public Recs recs { get; set; }
public string ItineraryCount { get; set; }
}
public partial class Recs
{
public string amountField { get; set; }
public string travelTimeField { get; set; }
public FSegment fSegmentField { get; set; }
public string itineraryNumberField { get; set; }
}
public class FSegment
{
public List<Segment> OutProperty {get;set;}
}
public class Segment
{
public string nameField { get; set; }
public string cityField { get; set; }
public string countryField { get; set; }
}
Try to use the following for your Classes and their Properties:
[DataContract]
public class Contact
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
Hacking like this helps in many cases, perhaps in your too (converting List to array):
public class FSegment
{
[XmlIgnore]
public List<Segment> OutProperty {get;set;}
[XmlArray("OutProperty");
public Segment[] _OutProperty
{
get { return OutProperty.ToArray(); }
set { OutProperty = new List<Segment>(value); }
}
}
I am not exactly sure how your provided class definition worked previously without any XML attribute/element definitions since your variable names are not the same as the XML identifiers, meaning that the serialization wouldn't populate the properties that it couldn't find a name for.
Nether the less, the main issue here is that you are trying to put a list into a normal property.
From the XML provided, OutProperty is a single sub element of FSegment and Segment is an array of sub elements of OutProperty, but in your provided code, you tried to make Segment an array sub element of FSegment.
The correct structure of the class definition should be as follows (also including the XML definitions)
[System.Xml.Serialization.XmlRoot(ElementName="TotalRecords")]
public class TotalRecords
{
[System.Xml.Serialization.XmlElement(ElementName="Recs")]
public Recs recs { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryCount")]
public string ItineraryCount { get; set; }
}
public partial class Recs
{
[System.Xml.Serialization.XmlElement(ElementName = "Amount")]
public string amountField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "TravelTime")]
public string travelTimeField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "FSegment")]
public FSegment fSegmentField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryNumber")]
public string itineraryNumberField { get; set; }
}
public class FSegment
{
[System.Xml.Serialization.XmlElement(ElementName = "OutProperty")]
public SegmentList OutProperty { get; set; }
}
public class SegmentList
{
[System.Xml.Serialization.XmlElement(ElementName = "Segment")]
public List<Segment> segmentField { get; set; }
}
public class Segment
{
[System.Xml.Serialization.XmlElement(ElementName = "Name")]
public string nameField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "City")]
public string cityField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "Country")]
public string countryField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "No")]
public int segmentNoField { get; set; }
}
Please note that in the above structure, Segment is a list object under the OutProperty object, which resides under the FSegment object.
Using this class structure to load your XML produces the (assumed) correct data in the created objects.
Using the XML definitions allows you to decouple the actual names of class properties from what they are called in the XML data. This allows you to changes the one or the other without affecting the other one, which is useful when you don't control the creation of the XML data.
If you don't want all the XML definitions in your code, change the names of the classes so that you can name your properties the same as what they are called in the XML file. That will allow you couple everything directly

Categories