Class won't serialize into JSON using unity's JSONUtility - c#

I have the following class, which is serializable and only has strings as fields:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class Cabeza
{
string id, urlOBJ, urlTextura, pathOBJbajado, pathTexturaBajada;
public string Id { get; set; }
public string UrlOBJ { get; set; }
public string UrlTextura { get; set; }
public string PathOBJbajado { get; set; }
public string PathTexturaBajada { get; set; }
public Cabeza (string nuevoId)
{
Id = nuevoId;
UrlOBJ = nuevoId +".obj";
UrlTextura = nuevoId + ".png";
}
}
As far I know it should be possible to obtain a JSON from it...However, JsonUtility.ToJson() returns just { }. How is this possible? What am I missing?

The documentation mentions (but doesn't make clear) that .ToJson() serializes fields, not properties.
I think the following code would work as you intend:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class Cabeza
{
public string Id;
public string UrlOBJ;
public string UrlTextura;
public string PathOBJbajado;
public string PathTexturaBajada;
public Cabeza (string nuevoId)
{
Id = nuevoId;
UrlOBJ = nuevoId +".obj";
UrlTextura = nuevoId + ".png";
}
}

Related

How can I actually use JSON in C#?

I have a Json file that was deserialized from a Json Api-Call, now I have to use this file as an object in the main program.
Here is a small section of it:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Api1
{
public class EcmSimpleField
{
public string value { get; set; }
public string displayName { get; set; }
public string internalName { get; set; }
public string dbName { get; set; }
public bool visible { get; set; }
public string type { get; set; }
}
public class BaseParameter
{
public string value { get; set; }
public string type { get; set; }
}
public class SystemField
{
public string value { get; set; }
public string type { get; set; }
}
How can I use this file as an object in the main program and work with it?
Create a class for the json like you shared above and use deserialise it using Newtonsoft.json dll or any other library.
var obj = JsonConvert.DeserializeObject<YourClass>(jsonString);
This thread will probably help you:
How can I parse JSON with C#?
If your JSON file has changing parameters then the parameters will need to be retrieved in arrays because the array index will always be the same even if the "parameter" changes.

C# filtering json results from restclient

I am completely new to C# and have zero background in the language.
The only programming language I am an expert in is SQL.
My situation:
I have a an API url from a website my company uses to monitor product levels in tanks.
The API returns a json list of the tanks (location, tank id, tank size, current level, etc.).
My goal is to create a windows form application with an input field.
The user types the name of the location, clicks a button, and sees the information for any tanks at that location.
What I have tried:
What I have done so far:
Again, I have zero knowledge of programming so do not be critical if I have done things in very unusual/inefficient ways.
I have managed to create a windows form that has a button and text box.
When the button is clicked, the text box is populated with all of the tank data from the API.
I can't figure out how to filter the data that has been returned.
My current code is below...
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using RestSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using static APIform.Form1;
namespace APIform
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var client = new RestClient("https://{{my tank monitor website}}/admin/data_feed_configs/140.json");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("auth-token", "{{my token}}");
request.AddHeader("auth-email", "{{my authorization email}}");
request.AddHeader("Authorization", "{{my auth code}}");
request.AddHeader("Cookie", "{{cookies}}");
IRestResponse response = client.Execute(request);
var data = response.Content;
JArray jsonArray = JArray.Parse(data);
textBox1.Text = jsonArray.ToString();
}
}
}
I have added a model class TankClass that resembles the text returned from the request.
public class TankClass
{
public string location_name { get; set; }
public string owner_name { get; set; }
public string tank_id { get; set; }
public string tank_name { get; set; }
public string product_name { get; set; }
public int tank_size { get; set; }
public string sensor_value { get; set; }
public string reading_inches { get; set; }
public string reading_volume { get; set; }
public string available_capacity { get; set; }
public int fill_percentage { get; set; }
public string fill_status { get; set; }
public string alert_status { get; set; }
public int days_to_empty { get; set; }
public string battery_level { get; set; }
public string product_sku { get; set; }
public string reading_time { get; set; }
public string division { get; set; }
}
Everything I try to deserialize/filter the results does not seem to be working.
What do I need to add into the code to make this work?
I have a second text box (textbox2) on the form.
This is where the user will enter "Warehouse 1" for example.
When they then hit the button, I would like only tanks at Warehouse 1 to show in the textbox1 field.
With my current code, this is a sample of what shows in the textbox1 field when clicking the button:
[
{
"location_name": "Warehouse 1",
"owner_name": "ABC Oil, Inc.",
"tank_id": "W00813862",
"tank_name": "Dow - Desitherm (TEG) Tank #M-20-065",
"product_name": "Dow - Desitherm (TEG)",
"tank_size": 2005.0,
"sensor_value": "2.379",
"reading_inches": "29.6",
"reading_volume": "908.2",
"available_capacity": "1096.8",
"fill_percentage": 45,
"fill_status": "COULD",
"alert_status": "",
"days_to_empty": 124.4,
"battery_level": "6.1",
"product_sku": "",
"reading_time": "2020-09-16T10:55:35-04:00",
"division": "1024"
},
{
"location_name": "Warehouse 2",
"owner_name": "ABC Oil, Inc.",
"tank_id": "Z057101",
"tank_name": "OSI 84 - Diesel Exhaust Fluid (DEF)",
"product_name": "Diesel Exhaust Fluid (DEF)",
"tank_size": 8806.0,
"sensor_value": "2554.0 | 3263.0",
"reading_inches": "76.3",
"reading_volume": "4868.8",
"available_capacity": "3937.2",
"fill_percentage": 55,
"fill_status": "GOOD",
"alert_status": "",
"days_to_empty": 14.5,
"battery_level": "-",
"product_sku": "",
"reading_time": "2020-09-16T10:59:00-04:00",
"division": ""
},
.
.
.
]
My Program.cs tab:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using RestSharp;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Security.Principal;
using System.Text;
using System.IO;
using static APIform.Form1;
namespace APIform
{
public class TankClass
{
public string location_name { get; set; }
public string owner_name { get; set; }
public string tank_id { get; set; }
public string tank_name { get; set; }
public string product_name { get; set; }
public double tank_size { get; set; }
public string sensor_value { get; set; }
public string reading_inches { get; set; }
public string reading_volume { get; set; }
public string available_capacity { get; set; }
public int fill_percentage { get; set; }
public string fill_status { get; set; }
public string alert_status { get; set; }
public double days_to_empty { get; set; }
public string battery_level { get; set; }
public string product_sku { get; set; }
public DateTime reading_time { get; set; }
public string division { get; set; }
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
In your class just change tank_size and days_to_empty to a double and reading_time to DateTime.
Then Deserialize into a List<TankClass>
var listOfTanks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<TankClass>>(data);
Then with the form data, you can use Linq to filter the results:
var returnValues = listOfTanks.Where(x => x.location_name == TextBox1.Text);

How to deserialize a JSON with array of strings using "System.Runtime.Serialization.Json" class in C#?

I am working with C# project in which, most data was of basic type all these days such as string, int, bool. Our client imprlements the JSON with System.Runtime.Serialization.Json, where we deserialize JSON sent from a server that is implemented in C++.
So for instance if I had to De-serialize a JSON sent from the server with 2 string keys such as:
{
"key1":"value1",
"key2":"value2"
}
we would define a class such as
[DataContract]
public class DeserializeKeys
{
[DataMember] public string key1 { get; set; }
[DataMember] public string key2 { get; set; }
};
Our server side code has changed to now send array of strings as a value as shown in the JSON object below:
{
"key1":"value1",
"key2":
[
"arrayValue1",
"arrayValue2",
"arrayValue3"
]
}
Please help me write a corresponding class that can deserialize the given JSON using "System.Runtime.Serialization.Json" class in C#.
I have already tried:
[DataContract]
public class DeserializeKeys
{
[DataMember] public string key1 { get; set; }
[DataMember] public string[] key2 { get; set; }
};
and
[DataContract]
public class DeserializeKeys
{
[DataMember] public string key1 { get; set; }
[DataMember] public List<string> key2 { get; set; }
};
but I am getting null for key2 upon deserialization.
What is the right way to define a class so that the JSON deserialization of array of string happens just as it works currently for a single string.
Seems to work correctly for me (both string[] and List<string> ) i'll assume that you deserialized it in a wrong way. Here is a minimal example that should get your started on fixing your app.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
namespace Serializator
{
public class Serializator
{
static public SomeClass ReadToObject(string json)
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(SomeClass));
var deserialized = ser.ReadObject(ms) as SomeClass;
ms.Close();
return deserialized;
}
}
[DataContract]
public class SomeClass
{
[DataMember] public string key1 { get; set; }
[DataMember] public List<string> key2 { get; set; }
};
class Program
{
static void Main(string[] args)
{
SomeClass sc = Serializator.ReadToObject("{\"key1\":\"value1\", \"key2\":[\"arrayValue1\", \"arrayValue2\", \"arrayValue3\"]}");
foreach(var item in sc.key2)
{
Console.WriteLine(item);
}
}
}
}
As it seems the issue lay in a data format not serialization mechanizm (the values of keys were also serialized objects) here is an updated version for the particular format the application required.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
namespace Serializator
{
public class Serializator
{
static public Object ReadToObject(string json, Type t)
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
DataContractJsonSerializer ser = new DataContractJsonSerializer(t);
var deserialized = ser.ReadObject(ms);
ms.Close();
return deserialized;
}
}
[DataContract]
public class IntermediateClass
{
[DataMember] public string error { get; set; }
[DataMember] public List<string> group { get; set; }
};
[DataContract]
public class ErrorClass
{
[DataMember] public string ErrorCode { get; set; }
[DataMember] public string ErrorMessage { get; set; }
};
public class GroupClass
{
[DataMember] public int ID { get; set; }
[DataMember] public string Name { get; set; }
}
public class CombinedClass
{
public ErrorClass error { get; set; }
public List<GroupClass> group { get; set; }
}
class Program
{
static void Main(string[] args)
{
CombinedClass cb = new CombinedClass();
IntermediateClass ic = (IntermediateClass)Serializator.ReadToObject("{\"error\":\"{\\n \\\"ErrorCode\\\" : 0,\\n \\\"ErrorMessage\\\" : \\\"Success.\\\"\\n}\\n\",\"group\":[\"{\\n \\\"ID\\\" : 1,\\n \\\"Name\\\" : \\\"Student1\\\"\\n}\\n\",\"{\\n \\\"ID\\\" : 2,\\n \\\"Name\\\" : \\\"Student2\\\"\\n}\\n\"]}", typeof(IntermediateClass));
cb.group = new List<GroupClass>();
foreach (var item in ic.group)
{
cb.group.Add((GroupClass)Serializator.ReadToObject(item, typeof(GroupClass)));
}
cb.error = (ErrorClass)Serializator.ReadToObject(ic.error, typeof(ErrorClass));
Console.WriteLine(cb.error.ErrorCode);
Console.WriteLine(cb.error.ErrorMessage);
Console.WriteLine(cb.group[0].Name);
Console.WriteLine(cb.group[0].ID);
Console.WriteLine(cb.group[1].Name);
Console.WriteLine(cb.group[1].ID);
}
}
}

Deserialize XML with XmlSerializer where parent and child have the same tag

I'm having difficulty parsing an XML string where the parent and child nodes have the same tag name. Obviously, I could replace the open/close tags with empty strings and parse with the code below, but that's not elegant.
I've searched and see that there are answers for how to do this with XDocument, but I specifically would like to do this with XmlSerializer (if possible).
Below is a minimal, reproducable example.
Example XML:
<AddJob>
<AddJob RequestStatus="OK" RequestMessage="Job successfuly added [testPrintServer.tif, PES_Carpet_16C_76.2 x 50.8 dpi_170517_Normal]" UUID="74ad5971-7baf-49ce-b85b-ee08188d5721" />
</AddJob>
Parsing code:
public class XmlHelper
{
public static T Deserialize<T>(string xml)
{
var serializer = new XmlSerializer(typeof(T));
T result;
using (var reader = new StringReader(xml))
{
result = (T)serializer.Deserialize(reader);
}
return result;
}
}
Data model:
[XmlRoot("AddJob")]
public class AddJob
{
[XmlAttribute]
public string RequestStatus { get; set; }
[XmlAttribute]
public string RequestMessage { get; set; }
[XmlAttribute("UUID")]
public string RipJobId { get; set; }
}
Calling code:
var addedJobResponse = XmlHelper.Deserialize<AddJob>(exampleXml);
Your data model doesn't match your xml structure.
Please use something like that:
[XmlRoot("AddJob")]
public class AddJob
{
[XmlElement(ElementName = "AddJob")]
public List<NestedAddJob> AddJobs { get; set; }
}
public class NestedAddJob
{
[XmlAttribute]
public string RequestStatus { get; set; }
[XmlAttribute]
public string RequestMessage { get; set; }
[XmlAttribute("UUID")]
public string RipJobId { get; set; }
}
The nested AddJob elements look like an array and you cannot have an array at the root. So add a Root class like code below :
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication75
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = "<AddJob>" +
"<AddJob RequestStatus=\"OK\" RequestMessage=\"Job successfuly added [testPrintServer.tif, PES_Carpet_16C_76.2 x 50.8 dpi_170517_Normal]\" UUID=\"74ad5971-7baf-49ce-b85b-ee08188d5721\" />" +
"</AddJob>";
Root job = XmlHelper.Deserialize<Root>(xml);
}
}
public class XmlHelper
{
public static T Deserialize<T>(string xml)
{
var serializer = new XmlSerializer(typeof(T));
T result;
using (var reader = new StringReader(xml))
{
result = (T)serializer.Deserialize(reader);
}
return result;
}
}
[XmlRoot("AddJob")]
public class Root
{
public AddJob AddJob { get; set; }
}
public class AddJob
{
[XmlAttribute]
public string RequestStatus { get; set; }
[XmlAttribute]
public string RequestMessage { get; set; }
[XmlAttribute("UUID")]
public string RipJobId { get; set; }
}
}

Razor View Engine in Console App with Complex Bass Class

I'm using the Razor view engine to render some HTML which will then live within an XML document. the base class I'm using has a number of properties, along with a static method which will return a list of that object (using Dapper to populate the list). I'm having trouble executing the method since it needs to return the base class, which is an abstract class. Some sample code is below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dapper;
using System.Data.SqlClient;
using System.Configuration;
using System.ComponentModel;
using System.IO;
namespace LocalBranchesPOC
{
public abstract class PersonData : TemplateBase
{
#region Properties
public string RecordId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string County { get; set; }
public string State { get; set; }
public string Country { get; set; }
public string Zip { get; set; }
public string Phone { get; set; }
public string Variable1 { get; set; }
public string Variable2 { get; set; }
public string Variable3 { get; set; }
#endregion
public static List<PersonData> GetPeople()
{
const string QUERY = "SELECT [RecordId], [Name], [Address], [City], [County], [State], [Country], [Zip], [Phone], [Variable1], [Variable2], [Variable3] FROM Data.Person";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["BranchLocator"].ConnectionString))
{
return getPeople(QUERY, conn);
}
}
private static List<PersonData> getPeople(string QUERY, SqlConnection conn)
{
conn.Open();
var result = conn.Query<PersonData>(QUERY).ToList();
conn.Close();
return result;
}
}
public abstract class TemplateBase
{
[Browsable(false)]
public StringBuilder Buffer { get; set; }
[Browsable(false)]
public StringWriter Writer { get; set; }
public TemplateBase()
{
Buffer = new StringBuilder();
Writer = new StringWriter(Buffer);
}
public abstract void Execute();
// Writes the results of expressions like: "#foo.Bar"
public virtual void Write(object value)
{
// Don't need to do anything special
// Razor for ASP.Net does HTML encoding here.
WriteLiteral(value);
}
// Writes literals like markup: "<p>Foo</p>"
public virtual void WriteLiteral(object value)
{
Buffer.Append(value);
}
}
}
Basically my call to PersonData.GetPeople() is failing because the PersonData class is abstract. Any thoughts would be appreciated. I'm using the example from here as my guide.
You're trying to merge the model and the view.
Don't do that; it cannot possibly work.
Instead, pass the model to the view as a separate property, perhaps loading it in the TemplateBase constructor.

Categories