How can we hide a property in WebAPI? - c#

I have a model say under
public class Device
{
public int DeviceId { get; set; }
public string DeviceTokenIds { get; set; }
public byte[] Data { get; set; }
public string FilePwd { get; set; }
}
Now I have a ASP.net Web API where there is a POST method as under
[HttpPost]
[Route("AddDeviceRegistrations")]
public void InsertDeviceRegistrations(Device device)
If I expose the WebAPI, obviously all the fields will be available e.g.
{
"DeviceId": 1,
"DeviceTokenIds": "sample string 2",
"Data": "QEBA",
"FilePwd": "sample string 3"
}
What I want is that, whenever I expose my WebAPI, the DeviceID should not get expose. I mean I am looking for
{
"DeviceTokenIds": "sample string 2",
"Data": "QEBA",
"FilePwd": "sample string 3"
}
Is it possible? If so how?
I can solve the problem by changing the function signature as
public void InsertDeviceRegistrations(string deviceTokenIds, byte[] data, string FilePwd).
But I wanted to know if it can be possible or not ?
If so , how?
Thanks in advance.

I just figured out
[IgnoreDataMember]
public int DeviceId { get; set; }
The namespace is System.Runtime.Serialization
More information IgnoreDataMemberAttribute Class
Learnt something new today.
Thanks All.

There's good practice to use View Models for all GET/POST requests.
In you case you should create class for receiving data in POST:
public class InsertDeviceViewModel
{
public string DeviceTokenIds { get; set; }
public byte[] Data { get; set; }
public string FilePwd { get; set; }
}
and then map data from view model to you business model Device.

If you are using Newtonsoft.Json
you can hide the properties like this:
public class Product
{
[JsonIgnore]
public string internalID { get; set; };
public string sku { get; set; };
public string productName { get; set; };
}
and your serialized response will not include the internalID property.

The use of the Attribute [NonSerialized] on top of the Property stops its from being Serialized in the outputting JSON/XML .
public class Device
{
[NonSerialized]
public int DeviceId { get; set; }
public string DeviceTokenIds { get; set; }
public byte[] Data { get; set; }
public string FilePwd { get; set; }
}

If you want to hide the data member of Resonse class with null parameter. Go to your project WebApiConfig file residing in App_start folder, add the following code:
var jsonConfig = config.Formatters.JsonFormatter;
jsonConfig.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;

Related

First time using NewtonSoft (JsonConvert.DeserializeObject<>() for deserializing JSON versus System.Text.Json (JsonSerializer.Deserialize<>()

​Using VS 2019, Dot Net Core, Azure Function. HttpTrigger.
I've worked with JSON files previously in .Net Desktop and Server app dev. So, don't know what's happening in Azure and with Newtonsoft. When I try and dump the value of wht.YourName.last, I get the error,
Object reference not set to an instance of an object
which confuses me because in my other programming with System.Text.Json, if I have a class model for a JSON file structure that has a child, the usual function call I use, which is JsonSerializer.Deserialize<jsonclass>(jsonstring), it has no problem setting up the child of the parent parent (reference below, class structure).
Is there a difference between the two function implementations, JsonConvert.DeserializeObject and JsonSerializer.Deserialize?
All of the code samples I've seen seem for Newtonsoft's method seem straight forward as its counterpart in dot net, which doesn't require me to have to do any pre-initalization of the NameBlock class/object.
Hope I explained that well enough considering my brain is kind of fried learning Azure.
Here is my deserialization code using Newtonsoft's method:
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
WebhookTest wht = JsonConvert.DeserializeObject<WebhookTest>(requestBody);
Raw dump of httprequest.Body:
{
"FormID":"1081011",
"UniqueID":"178165183",
"support_request":"",
"your_name":{
"first":"Testy",
"last":"Tester"
},
"email":"jxxxx#gxxxcxxxaxxxxxxxx.com",
"phone":"(111) 867-5309",
"upload_a_file_optional":"",
"request_details":"Testing latest revision of Azure function that deserializes JSON data into a class object."
}
This is what my class structure looks like:
public class NameBlock
{
public string first { get; set; }
public string last { get; set; }
}
public class WebhookTest
{
public string FormID { get; set; }
public string UniqueID { get; set; }
public string SupportRequest { get; set; }
public NameBlock YourName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
[JsonProperty("Uploadafile(optional)")]
public string UploadafileOptional { get; set; }
public string RequestDetails { get; set; }
}
The reason for the error Object reference not set to an instance of an object is the code can't find wht.YourName(because wht.YourName is null). Please change your class structure to:
public class NameBlock
{
public string first { get; set; }
public string last { get; set; }
}
public class WebhookTest
{
public string FormID { get; set; }
public string UniqueID { get; set; }
public string SupportRequest { get; set; }
[JsonProperty(PropertyName = "your_name")]
public NameBlock YourName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
[JsonProperty("Uploadafile(optional)")]
public string UploadafileOptional { get; set; }
public string RequestDetails { get; set; }
}
Just add a line [JsonProperty(PropertyName = "your_name")]
By the way:
When we use System.Text.Json, it will relate your_name(in request json) with YourName(in class structure) automatically according to hump law. But when we use Newtonsoft.Json, it can't do it. So it can't relate your_name with YourName. We need to add [JsonProperty(PropertyName = "your_name")] to let the code know how to relate the two properties.

How can I deserialise a JSON result where its Root is a unique ID into an Object class

I am currently trying to learn to work with API systems using C# .net core 3 and Newtonsoft.
The following call to Steam API is what I am using
for specific game details. For example http://store.steampowered.com/api/appdetails?appids=72850
This returns JSON similar to this ( I have cut it down for simplicity )
{
"72850": {
"success": true,
"data": {
"type": "game",
"name": "The Elder Scrolls V: Skyrim",
"steam_appid": 72850,
"required_age": 0,
"is_free": false
}
}
}
Each return has the unique ID as the root in this case 72850 and I am at a loss on how to map this into an object class so I can process this data. The "data" element is what I am really interested in but as a beginner, I am at a loss.
This API indexes its response using the internal Identifier of the Item requested.
This is a common scenario and it's also a quite efficient method to organize objects based on an Indexer, which can then be used to store or retrieve these objects, from a database, for example.
A common way to deserialize JSON object indexed like this, is to use a Dictionary, where the Key is Indexer and the Value the RootObject of the class structure (the Model) that further describes the JSON properties.
Some notes on the current JSON:
The API looks like it's built to represent the JSON on a HTML document, since the internal strings are formatted ready for presentation on a HTML page. This can be less useful when used elsewhere and can also create a problem when deserializing.
I've added a trivial clean-up, replacing what can cause a problem for sure:
json = json.Replace(#"\/", "/").Replace(#"\t", "");
I've added some more properties and classes to those presented in the question: it may be useful to see when a JsonProperty attribute is needed and when is it's not. For example: the [JsonProperty("type")] attribute is added to the public string GameType { get; set; } property, since Type is a keyword that may be misinterpreted, as is Name etc.
Json.Net is not case sensitive, so the JSON property background can be assigned to a .Net property public Uri Background { get; set; } without problem.
A couple of WebSites that provide a free service to format, validate and convert JSON object to a class model:
JsonFormatter - Formatting, validation
QuickType - Multi-language Class Model generator
Download the JSON using the WebClient.DownloadString() method, clean up the JSON and deserialize:
var steamUri = new Uri("https://store.steampowered.com/api/appdetails?appids=72850")
string json = new WebClient(steamUri).DownloadString();
json = json.Replace(#"\/", "/").Replace(#"\t", "");
var steamObj = JsonConvert.DeserializeObject<Dictionary<long, SteamApps.SteamAppDetails>>(json);
Class structure:
public class SteamApps
{
public class SteamAppDetails
{
public bool Success { get; set; }
public Data Data { get; set; }
}
public class Data
{
[JsonProperty("type")]
public string GameType { get; set; }
[JsonProperty("name")]
public string GameName { get; set; }
[JsonProperty("steam_appid")]
public long SteamAppid { get; set; }
[JsonProperty("required_age")]
public long RequiredAge { get; set; }
[JsonProperty("is_free")]
public bool IsFree { get; set; }
[JsonProperty("short_description")]
public string ShortDescription { get; set; }
[JsonProperty("supported_languages")]
public string Languages { get; set; }
[JsonProperty("header_image")]
public string HeaderImage { get; set; }
public string WebSite { get; set; }
[JsonProperty("price_overview")]
public PriceOverview PriceOverview { get; set; }
public Dictionary<string, bool> Platforms { get; set; }
public List<Screenshot> Screenshots { get; set; }
public Uri Background { get; set; }
public List<Category> Categories { get; set; }
}
public class PriceOverview
{
public string Currency { get; set; }
public long Initial { get; set; }
public long Final { get; set; }
[JsonProperty("discount_percent")]
public decimal DiscountPercent { get; set; }
[JsonProperty("initial_formatted")]
public string InitialFormatted { get; set; }
[JsonProperty("final_formatted")]
public string FinalFormatted { get; set; }
}
public partial class Screenshot
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("path_thumbnail")]
public string PathThumbnail { get; set; }
[JsonProperty("path_full")]
public string PathFull { get; set; }
}
public partial class Category
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
}
}
Since you only need the "Data" element from the json, it is fairly simple using Newtonsoft. First make a class with all the fields that the Data element contains as shown below:
public class Data
{
public string Type { get; set; }
public string Name { get; set; }
public long Steam_AppId { get; set; }
public int Required_Age { get; set; }
public bool Is_Free { get; set; }
}
Now in order to map the json response, which I'm assuming is stored in a string at the moment, you have to Deserialize it to map to your C# class. And you can do that very easily:
Edit: A more elegant solution which avoids all the string manipulation nuisance
//You already have this but I created it in order to test
string jsonResult = "{ \"72850\": " +
"{ \"success\": true, \"data\": " +
"{ \"type\": \"game\", \"name\": \"The Elder Scrolls V: Skyrim\", " +
"\"steam_appid\": 72850, \"required_age\": 0, \"is_free\": false } }";
//JObject is a class in Newtonsoft library for handling json objects
JObject jObject = JObject.Parse(jsonResult);
//Since you're sending a request to the api, either you already have the id
//"72850" or can extract it easily from uri. This line gets data's value
//by 1st searching for key = "72850" and then within that a key = "data"
JToken dataToken = jObject["72850"]["data"];
Data data = dataToken.ToObject<Data>();
Reference: https://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm
Older solution
//getting the value portion of data element/key
string jsonData = "{" + jsonResult.Substring(jsonResult.IndexOf("\"type"));
//removing the extra } from the end
jsonData = jsonData.TrimEnd('}');
//map the json string to a C# object
var dataObj = JsonConvert.DeserializeObject<Data>(jsonData);
So now you'll see the json values mapped to your Data object which in this case is dataObj. Feel free to ask questions if anything's not clear. Cheers!

nested json deserialization - need another set of eyes

I have been trying to get this json to deserialize for two days now using RestSharp. I have gone through the RestSharp github site, looked at countless examples, and spent much time here on Stack Overflow to try and find the answer to no avail. My code had previously worked perfectly but the vendor changed their API version and I was forced to do an update to keep using the application for my legal practice. My json is as follows(client info has been removed and replaced with generic info):
{
"data":[
{
"id":1035117666,
"client":
{
"id":905422394,
"name":"client1"
},
"display_number":"11-00012",
"description":"General",
"practice_area":
{
"id":4269978,
"name":"Business"
},
"status":"Open",
"open_date":"2011-12-14",
"close_date":null,
"billing_method":"hourly"
},
{
"id":1035117768,
"client":
{
"id":905422506,
"name":"client2"
},
"display_number":"12-00037",
"description":"HOA",
"practice_area":
{
"id":4269978,
"name":"Business"
},
"status":"Open",
"open_date":"2012-08-07",
"close_date":null,
"billing_method":"hourly"
}
],
"meta":
{
"paging":
{
"next":"https://app.goclio.com/api/v4/matters.json?fields=id%2C+client%7Bid%2C+name%7D%2C+display_number%2C+description%2C+practice_area%7Bid%2C+name%7D%2C+status%2C+open_date%2C+close_date%2C+billing_method&limit=2&page_token=BAh7BjoLb2Zmc2V0aQc%3D--b1ea3eba20c8acefbcdfc7868debd1e0ee630c64&status=Open"
},
"records":91
}
}
I built the following schema within my c# code:
public class MatterList
{
public List<Matter> matters { get; set; }
public Meta meta { get; set; }
}
public class Meta
{
public Paging paging { get; set; }
public int records { get; set; }
}
public class Paging
{
public string previous { get; set; }
public string next { get; set; }
}
[DeserializeAs(Name = "data")]
public class Matter
{
public int id { get; set; }
public Client client { get; set; }
public string display_number { get; set; }
public string description { get; set; }
public PracticeArea practice_area { get; set; }
public string status { get; set; }
public DateTime open_date { get; set; }
public DateTime close_date { get; set; }
public string billing_method { get; set; }
public string type = "matter";
}
public class PracticeArea
{
public int id { get; set; }
public string name { get; set; }
}
public class Client
{
public int id { get; set; }
public string name { get; set; }
}
When I run the RestSharp deserialize method I am sending the result to an object of type MatterList using the following line of code
MatterList matterList = jsonHandler.Deserialize<MatterList>(response);
I have so far attempted to deserialize without the Meta or Paging POCO classes with the accompanying change to the MatterList class (taking out the Meta property).
I have tried with and without the [DeserializeAs(Name="data")] directive.
I have tried to set the RootElement of the json response prior to deserialization.
I have tried to shorthand the deserialization by combining it with the Execute request code
IRestResponse<MatterList> matterList = client.Execute<MatterList>(request);
I have created a container class called MatterContainer which I placed between MatterList and Matter classes in the schema:
public class MatterList
{
public List<MatterContainer> matters { get; set; }
}
public class MatterContainer
{
public Matter matter { get; set; }
}
public class Matter
{
public int id { get; set; }
public Client client { get; set; }
public string display_number { get; set; }
public string description { get; set; }
public PracticeArea practice_area { get; set; }
public string status { get; set; }
public DateTime open_date { get; set; }
public DateTime close_date { get; set; }
public string billing_method { get; set; }
public string type = "matter";
}
I know I am getting the json response back from the server correctly so my request is proper and MatterList is not null after deserialization. The problem is that I cannot get the deserialization to actually populate the List matters within the MatterList class.
I have been looking at this off and on for two days and cannot get past this hurdle. If anyone sees what I did wrong I would greatly appreciate the insight, I am at a point where I cannot progress further with my application.
Thanks!
I think your [DeserializeAs(Name = "data")] attribute is in the wrong place. Try putting it in the root class instead:
public class MatterList
{
[DeserializeAs(Name = "data")]
public List<Matter> matters { get; set; }
public Meta meta { get; set; }
}
alternatively, try renameing that property to data

Json response to class mapping Restsharp deserializing

I am using RestSharp to consume a restful webservice. I am using the built in Json Deserializer to deserialize the response.
This is the response.
[{"id":"1","latitude":"18.0155848","longitude":"-77.4988293","rating":"1","streetid":"1","username":"joel","verified":"1"},{"id":"2","latitude":"18.0155892","longitude":"-77.498774","rating":"1","streetid":"2","username":"joel","verified":"0"},{"id":"3","latitude":"18.0227736","longitude":"-77.4980039","rating":"1","streetid":"3","username":"joel","verified":"0"}]
These are the models its being mapped to.
List<Pothole> list = new List<Pothole>();
public class Pothole
{
//getters and setters for the attributes of Pothole Model
public long Id { get; set;}
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Rating{ get;set;}
public long StreetId { get; set; }
public string Username { get; set; }
public bool Verified { get; set; }
}
However when I make the call the data is not being deserialized.I am wondering if there is a problem with the json response to the class mapping. I am mapping the response to a list of potholes due to an array of pothole objects being returned. I check the HTTP status code and the content of the response so the data is being returned, its just the deserializing causing a problem.
Try this:
public class Pothole
{
public string id { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public string rating { get; set; }
public string streetid { get; set; }
public string username { get; set; }
public string verified { get; set; }
}
C# is case sensitive and so the reflection that takes place in populating the C# object will look for properties with names EXACTLY like those in the JSON string.
Also, if you're using Visual Studio 2012 SP 1 you can actually paste JSON text as a C# class. Pretty handy.
Or you can also use : Json2Csharp
generate c# classes from json
Late to the party but I thought I'd throw in my $0.02. I am using an unmodified version of RestSharp.Portable 1.6.2 Xamarin PCL
I have json as follows:
{"blah":{"iPAddress":"10.1.1.x","cPU":"1 vCPU","dNSName":"blah.blah.com"}}
with the class below, the deserialzation does not work for CPU, works for DSName, and IPAddress though.
public class Blah
{
public string CPU { get; set; }
public string DNSName { get; set; }
public string IPAddress { get; set; }
}
However if I change CPU to cPU it works fine.
public class Blah
{
public string cPU { get; set; }
public string DNSName { get; set; }
public string IPAddress { get; set; }
}
So, feels like a bug, just wanted to contribute.

Setting up a class to contain a list of objects

I am setting a class in C# to hold a response that I will be receiving from a web service call. I'm using RestSharp to handle the calling / parsing of the JSON data.
The web service documentation describes the response as:
OUTPUT: JSON object similar to example below.
{
"response":"[success] or [failed]",
"messages":"Process succeeded.",
"logonkey":"[logon key]",
"tokenkey":"[security token]",
"reccount":"1",
"filelist":
{
"fileid":"12345",
"status":"N",
"filename":"data.tar",
"fulfilled":"2012-06-15"
}
}
My question is how can I define the filelist array element in my class?
I was thinking something like this:
public class Files
{
public string Response { get; set; }
public string Messages { get; set; }
public string LogonKey { get; set; }
public string TokenKey { get; set; }
public int RecordCount { get; set; }
public List<FileList>
}
public class FileList
{
public string FileID { get; set; }
public string Status { get; set; }
public string Filename { get; set; }
public DateTime Fulfilled { get; set; }
}
However, I'm having a problem with the "public List" statement.
Any suggestions on the best way to handle this scenario would be appreciated.
Also you forgot to give it a name, for example try this
public List<FileList> MyFavouriteList {get;set;}.
A proprety is declared like this "access modifier", "Type", "identifier(or name)", "getter and setter".
The filelist in JSON sample doesn't look like list of objects. Instead it is a single object.
You could try,
public class Files
{
public string Response { get; set; }
public string Messages { get; set; }
public string LogonKey { get; set; }
public string TokenKey { get; set; }
public int RecordCount { get; set; }
public FileList File {get; set; }
}
If you are sure the filelist in JSON is really list of object, you could try,
public List<FileList> Files = new List<FileList>();

Categories

Resources