Deserialize Json with varying dictionary size in unity - json

I am using newtonsoft.json in unity and trying to deserialize from an api endpoint.
I have my Json response set up kind of like this..
{}pattern_order
{}LB
{}LC
Actual end point:
{"key":"value","pattern_order":{"LB":{"A":[{"order":["A","G","X","D"],"style":"SK"},{"order":["D","X","D"],"style":"SK"}],"B":[{"order":["A","D","X","G","C"],"style":"SK"},{"order":["C","X","D"],"style":"SK"},{"order":["D","G","X"],"style":"AT"}]},"LC":{"A":[{"order":["A","D","X","G","C"],"style":"AT"},{"order":["C","X","D"],"style":"SK"}],"B":[{"order":["A","D","X","G","C"],"style":"AT"},{"order":["C","X","D"],"style":"SK"}]}}}
Here, LB and LC have a similar structure, but I want to add more objects inside pattern_order.
What is the best way to deserialize such a json in unity?

After removing the . that shouldn't be there as mentioned I just have put it into Json2csharp which results in
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class A
{
public List<string> order { get; set; }
public string style { get; set; }
}
public class B
{
public List<string> order { get; set; }
public string style { get; set; }
}
public class LB
{
public List<A> A { get; set; }
public List<B> B { get; set; }
}
public class LC
{
public List<A> A { get; set; }
public List<B> B { get; set; }
}
public class PatternOrder
{
public LB LB { get; set; }
public LC LC { get; set; }
}
public class Root
{
public string key { get; set; }
public List<string> levels { get; set; }
public PatternOrder pattern_order { get; set; }
}
From there it is actually a simple step:
public class Thingy
{
public List<string> order;
public string style;
}
public class Root
{
public string key;
public List<string> levels;
// HERE YOU GO!
public Dictionary<string, Dictionary<string, Thingy[]>> pattern_order;
}
and
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
You can rename Thingy (and all other classes) to whatever you want ;)

Related

Deserializing JSON from URL - how do I add it to multiple objects

So basically I ran the JSON through jsonUtils which created an object, which turned out to be several objects.
So 2 questions please:
How to best populate objects from URL?
Can I select which objects to populate, i.e. I don't want to do all 20 objects?
In advance, thank you!!
WebClient client = new WebClient();
string myJSON = client.DownloadString("https://someURL.geojson");
var myClass = Newtonsoft.Json.JsonConvert.DeserializeObject(myJSON);
Console.Write(myClass.ToString());
public class PrecipType
{
public string units { get; set; }
public string value { get; set; }
}
public class Press
{
public string units { get; set; }
public string value { get; set; }
}
public class Atmo
{
public AirTemperature air_temp{ get; set; }
public Dewpoint dew_point{ get; set; }
public Wind { get; set; }
public Pressure pressure { get; set; }
}
public class ObsTime
{
public string units { get; set; }
public string value { get; set; }
}

Implementing deserialization with RestSharp and Newtonsoft.Json

I am rather new to c# but I am building something to help me at work. We have a REST API which I am trying to tap into but I am having issues when it comes to deserializing the response.
My code:
namespace BSRestCleint
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string key = "xxxxxxxx";
string endPoint = "https://api.broadsign.com:10889/rest";
private void bRun_Click(object sender, EventArgs e)
{
var client = new RestClient(endPoint);
var request = new RestRequest("/host/v14/by_id", Method.GET);
request.AddHeader("accept", "application/json");
request.AddHeader("Authorization", "Bearer " + key);
request.AddParameter("domain_id", "103947039");
request.AddParameter("ids", "195392183");
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
request.RequestFormat = DataFormat.Json;
var response = client.Execute<Host>(request);
var host = JsonConvert.DeserializeObject<Host>(response.Content);
oResponse.Text = host.Name;
}
}
}
And this is my class:
namespace BSRestCleint
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization.Json;
using System.IO;
public partial class Host
{
[JsonProperty("config_profile_bag_id")]
public long ConfigProfileBagId { get; set; }
[JsonProperty("container_id")]
public long ContainerId { get; set; }
[JsonProperty("db_pickup_tm_utc")]
public string DbPickupTmUtc { get; set; }
[JsonProperty("discovery_status")]
public long DiscoveryStatus { get; set; }
[JsonProperty("display_unit_id")]
public long DisplayUnitId { get; set; }
[JsonProperty("domain_id")]
public long DomainId { get; set; }
[JsonProperty("geolocation")]
public string Geolocation { get; set; }
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("nscreens")]
public long Nscreens { get; set; }
[JsonProperty("public_key_fingerprint")]
public string PublicKeyFingerprint { get; set; }
[JsonProperty("remote_clear_db_tm_utc")]
public string RemoteClearDbTmUtc { get; set; }
[JsonProperty("remote_reboot_tm_utc")]
public string RemoteRebootTmUtc { get; set; }
[JsonProperty("volume")]
public long Volume { get; set; }
}
}
Finally the returning json:
{
"not_modified_since":"2018-06-05T22:22:18Z",
"host":[
{
"active":true,
"config_profile_bag_id":0,
"container_id":0,
"db_pickup_tm_utc":"2018-01-11T10:12:55",
"discovery_status":0,
"display_unit_id":0,
"domain_id":103947039,
"geolocation":"(0,0)",
"id":195392183,
"license_end_date":null,
"licensed":true,
"name":"Broadsign Services - Mathias - 16x64",
"nscreens":0,
"primary_mac_address":"00:0c:29:e0:e6:22",
"public_key_fingerprint":"REDACTED",
"remote_clear_db_tm_utc":"1970-01-01T00:00:00",
"remote_reboot_tm_utc":"2017-12-12T10:17:23",
"secondary_mac_address":"",
"volume":-1
}
]
}
I know that if I only process this part my code works:
{
"active":true,
"config_profile_bag_id":0,
"container_id":0,
"db_pickup_tm_utc":"2018-01-11T10:12:55",
"discovery_status":0,
"display_unit_id":0,
"domain_id":103947039,
"geolocation":"(0,0)",
"id":195392183,
"license_end_date":null,
"licensed":true,
"name":"Broadsign Services - Mathias - 16x64",
"nscreens":0,
"primary_mac_address":"00:0c:29:e0:e6:22",
"public_key_fingerprint":"REDACTED",
"remote_clear_db_tm_utc":"1970-01-01T00:00:00",
"remote_reboot_tm_utc":"2017-12-12T10:17:23",
"secondary_mac_address":"",
"volume":-1
}
I'd like to know how I could make my code work to handle the whole json so that I don't need to regex the returning value. Some of the responses would return multiple instances unlike there where there's only 1. It's probably a very simple solution but my grasp of the language is rather minute as I am new to it.
Any help would be appreciated.
Since, you are getting the host as array inside the another root object so you can define a new class as which is wrapping Host (array)
public class RootObject
{
public DateTime not_modified_since { get; set; }
public List<Host> Host { get; set; }
}
deserialization code need to be updated as
var root = JsonConvert.DeserializeObject<RootObject>(response.Content);
If you see, here deserializtion will happen for RootObject instead of Host.
Now, to get all hosts, use the below code:
var hosts = root.Host;
Or the first host from received hosts
var firstHost = root.Host.First();
You can extract it like this, without introducing new class:
var js = JObject.Parse(response.Content);
var hosts = JArray.Parse(obj["host"].ToString());
foreach (JObject host in hosts)
{
var h = JsonConvert.DeserializeObject<Host>(host)
//do what you need to do with host
}
You mentioned that there can be multiple hosts, so, you have to convert it to JArray, and loop through the array.
use this as your Host class instead (renamed to RootObject)
public partial class RootObject
{
[JsonProperty("not_modified_since")]
public DateTimeOffset NotModifiedSince { get; set; }
[JsonProperty("host")]
public List<Host> Host { get; set; }
}
public partial class Host
{
[JsonProperty("active")]
public bool Active { get; set; }
[JsonProperty("config_profile_bag_id")]
public long ConfigProfileBagId { get; set; }
[JsonProperty("container_id")]
public long ContainerId { get; set; }
[JsonProperty("db_pickup_tm_utc")]
public DateTimeOffset DbPickupTmUtc { get; set; }
[JsonProperty("discovery_status")]
public long DiscoveryStatus { get; set; }
[JsonProperty("display_unit_id")]
public long DisplayUnitId { get; set; }
[JsonProperty("domain_id")]
public long DomainId { get; set; }
[JsonProperty("geolocation")]
public string Geolocation { get; set; }
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("license_end_date")]
public object LicenseEndDate { get; set; }
[JsonProperty("licensed")]
public bool Licensed { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("nscreens")]
public long Nscreens { get; set; }
[JsonProperty("primary_mac_address")]
public string PrimaryMacAddress { get; set; }
[JsonProperty("public_key_fingerprint")]
public string PublicKeyFingerprint { get; set; }
[JsonProperty("remote_clear_db_tm_utc")]
public DateTimeOffset RemoteClearDbTmUtc { get; set; }
[JsonProperty("remote_reboot_tm_utc")]
public DateTimeOffset RemoteRebootTmUtc { get; set; }
[JsonProperty("secondary_mac_address")]
public string SecondaryMacAddress { get; set; }
[JsonProperty("volume")]
public long Volume { get; set; }
}
}
then deserialize
var rootObject = JsonConvert.DeserializeObject<RootObject>(response.Content);
var hosts = rootObject .Host;

Newtonsoft Json is not serializing class

I have the following classes that I'm using to collect data and then return the structure in Json.
public class Outcome {
public int id { get; set; }
public string outcome { get; set; }
public string actionStep { get; set; }
public List<OutcomeActionResult> actionResults { get; set; }
public void setData(SqlDataReader reader, DateData dateData) {
this.id = Convert.ToInt32(reader["id"]);
this.outcome = Convert.ToString(reader["outcome"]);
this.actionStep = Convert.ToString(reader["action_step"]);
this.actionResults = new Outcomes().getActionResultByOutcomeId(this.id, dateData);
}
}
public class OutcomeActionResult {
public int id { get; set; }
public string actionResult { get; set; }
public ActionResultQuestion question { get; set; }
public void setData(SqlDataReader reader, DateData dateData) {
this.id = Convert.ToInt32(reader["id"]);
this.actionResult = Convert.ToString(reader["action_result"]);
this.question = new Outcomes().getActionResultQuestionByActionResultId(this.id, dateData);
}
}
public class ActionResultQuestion {
public int id { get; set; }
public string question { get; set; }
public bool isMultipleChoice { get; set; }
public List<MultipleChoiceOption> multipleChoiceOptions { get; set; }
ActionResultAnswer answer { get; set; }
public void setData(SqlDataReader reader, DateData dateData) {
this.id = Convert.ToInt32(reader["id"]);
this.question = Convert.ToString(reader["question"]);
this.isMultipleChoice = Convert.ToBoolean(reader["is_multi"]);
this.answer = new Outcomes().getActionResultAnswersByIdAndDate(this.id, dateData.year, dateData.month, dateData.day, dateData.shiftId);
}
}
public class ActionResultAnswer {
public int id { get; set; }
public string notes { get; set; }
public int employeeId { get; set; }
public int selectedAnswer { get; set; }
public string answer { get; set; }
public int year { get; set; }
public int month { get; set; }
public int day { get; set; }
public int shiftId { get; set; }
public void setData(SqlDataReader reader) {
this.id = Convert.ToInt32(reader["id"]);
this.notes = Convert.ToString(reader["notes"]);
this.employeeId = Convert.ToInt32(reader["employee_id"]);
this.selectedAnswer = reader.IsDBNull(reader.GetOrdinal("selected_answer")) ? -1 : Convert.ToInt32(reader["selected_answer"]);
this.answer = Convert.ToString(reader["answer"]);
this.year = Convert.ToInt32(reader["year"]);
this.month = Convert.ToInt32(reader["month"]);
this.shiftId = Convert.ToInt32(reader["shift_id"]);
}
}
As you can see, I have Outcome which contains a list of OutcomeActionResults each of which contains an ActionResultQuestion which has an ActionResultAnswer. Something like this:
Outcome -> List(OutcomeActionResult) --> ActionResultQuestion --> ActionResultAnswer
When I step through the code, all the data is being populated correctly and everything is fine. However, when I serialize the object structure to JSON it serializes everything except the ActionResultAnswer. Basically the deepest level of the structure gets chopped off. I've been unable to find anything that tells me why this is happening or how to have it not happen.
Probably ought to put the code that serializes the objects up here:
var response = outcomes.getOutcomesByClientAndDate(clientId, year, month, day, shiftId, dayOfWeek);
var json = JsonConvert.SerializeObject(response);
The answer property in your ActionResultQuestion class is not public. Therefore, it will not be serialized by Json.Net by default.
You can either make the property public...
public ActionResultAnswer answer { get; set; }
or, if you intend that it not be public, you can mark it with a [JsonProperty] attribute to allow the serializer to "see" it:
[JsonProperty]
ActionResultAnswer answer { get; set; }

Trying to check a json file for the correct parameters using JsonConvert.DeserisalizeObject<t>

I'm using the ACE code editor to gather Json and send it to my application. Once the Json hits the application, I need to make sure there are certain key's inside the json so I am using JsonConvert.DeserisalizeObject<t> to do this. Here's how:
public void SubmitReport(string JsonStringSend)
{
try
{
ReportItem RptItem = JsonConvert.DeserializeObject<ReportItem>(JsonStringSend);
}
catch(err)
{
return View(err);
}
}
and:
public class ReportItem
{
public Guid ReportID;
public bool RequiresFilter;
public string MimeType { get; set; }
public string ExternalID { get; set; }
public DateTime CreatedBy { get; set; }
public string ExecutionScript { get; set; }
public string ExecutionParameter { get; set; }
public string ExecutionOrderBy { get; set; }
public List<DynamicFilter> DynamicFilters { get; set; }
public bool RequiresOrgID { get; set; }
public QueryFilter ReportFilter { get; set; }
public QueryRule ReportRules { get; set; }
public List<QueryColumn> Columns { get; set; }
}
But for some reason, it bounces right over the catch even when I make sure some of the key's are incorrect. Am I not understanding the correct usage JsonConvert.DeserisalizeObject<t>? Or, is there a better way to be doing this check?
By default, the deserializer "tries it's best" to deserialize the object. But JSon.NET supports validation, the "straightforward" way is probably JSon Schema: http://www.newtonsoft.com/jsonschema.
Simple case can be handled with JSon.NET directly:
public class ReportItem
{
[JsonProperty(Required = Required.Always)]
public bool RequiresFilter;
[JsonProperty(Required = Required.Always)]
public string MimeType { get; set; }
public DateTime CreatedBy { get; set; }
public string ExecutionScript { get; set; }
public string ExecutionParameter { get; set; }
public string ExecutionOrderBy { get; set; }
public bool RequiresOrgID { get; set; }
}

How can I deserialization JSON in Windows Phone?

The first JSON is look like this
The second JSON is look like this
How can I deserialize them? I have been follow this example but it's not working.
Here's my code.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var w = new WebClient();
Observable
.FromEvent<DownloadStringCompletedEventArgs>(w, "DownloadStringCompleted")
.Subscribe(r =>
{
var deserialized =
JsonConvert.DeserializeObject<List<Place>>(r.EventArgs.Result);
PlaceList.ItemsSource = deserialized;
});
w.DownloadStringAsync(
new Uri("http://mobiilivantaa.lightscreenmedia.com/api/place"));
//For 2nd JSON
//w.DownloadStringAsync(
//new Uri("http://mobiilivantaa.lightscreenmedia.com/api/place/243"));
}
These are classes for 1st JSON.
public class Place
{
public string id { get; set; }
public string title { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public string www { get; set; }
}
public class RootObjectJSON1
{
public List<Place> Places { get; set; }
}
These are classes for JSON2
public class Address
{
public string street { get; set; }
public string postal_code { get; set; }
public string post_office { get; set; }
}
public class Image
{
public string id { get; set; }
public string filename { get; set; }
public string path { get; set; }
}
public class RootObjectJSON2
{
public string id { get; set; }
public string title { get; set; }
public string description { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public string www { get; set; }
public string phone { get; set; }
public string email { get; set; }
public string contact_person { get; set; }
public Address address { get; set; }
public List<Image> images { get; set; }
}
it looks that you should be deserializing object RootObjectJSON1 or RootObjectJSON2, e.g.:
var deserialized = JsonConvert.DeserializeObject<RootObjectJSON1>(r.EventArgs.Result);
Also it seems that collection Places should be with lowercase p at beginning or you need to tell Json.NET that this property should be deserialized with different name, e.g.:
[JsonProperty(PropertyName="places")]
public List<Place> Places { get; set; }
Generally I tend to use arrays for deserialization (from my experience works better) so I'll suggest to rewrite it to this:
public class RootObjectJSON1
{
public Place[] places { get; set; }
}
There is very good tool named json2csharp available at http://json2csharp.com/ - just put sample of JSON there and it will spit out classes in C# (doesn't detect DateTime so you might need to change that).