I have to create a post request in Json in this format.
{
"request": {
"application": "APPLICATION_CODE",
"auth": "API_ACCESS_TOKEN",
"notifications": [{
"send_date": "now", // YYYY-MM-DD HH:mm OR 'now'
"ignore_user_timezone": true, // or false
"content": "Hello world!"
}]
}
}
This is my first time serializing Json String and I have no idea how to do this, I have tried a few different things but could never get the exact format.
Would really appreciate any kind of help.
Thanks!
First, you cannot put comment on a json file, but I guess it was just there for now.
Then you can paste your json in converters like this one http://json2csharp.com/
And you get the following:
public class Notification
{
public string send_date { get; set; }
public bool ignore_user_timezone { get; set; }
public string content { get; set; }
}
public class Request
{
public string application { get; set; }
public string auth { get; set; }
public List<Notification> notifications { get; set; }
}
public class RootObject
{
public Request request { get; set; }
}
Now you need to fix a few issues that are required for JsonUtility:
[Serializable]
public class Notification
{
public string send_date;
public bool ignore_user_timezone;
public string content;
}
[Serializable]
public class Request
{
public string application;
public string auth;
public List<Notification> notifications;
}
[Serializable]
public class RootObject
{
public Request request;
}
Finally:
RootObject root = JsonUtility.FromJson<RootObject>(jsonStringFile);
You can also use SimpleJSON like this ;
string GetRequest () {
JSONNode root = JSONNode.Parse("{}");
JSONNode request = root ["request"].AsObject;
request["application"] = "APPLICATION_CODE";
request["auth"] = "API_ACCESS_TOKEN";
JSONNode notification = request ["notifications"].AsArray;
notification[0]["send_date"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
notification[0]["ignore_user_timezone"] = "true";
notification[0]["content"] = "Hello world!";
return root.ToString ();
}
Related
I'm having an issue while trying to read a Json string in unity.
I created Classes based on the json response im receiving
but im not able to deserialize this json
Where I did wrong, can anybody help?
{
"status": 200,
"isSuccess": true,
"message": "Suggestion Found",
"response": {
"result": [
{
"OriginalWord": "goodboy",
"suggests": [
{
"suggestWords": "good boy"
},
{
"suggestWords": "Cordoba"
},
{
"suggestWords": "Catawba"
},
{
"suggestWords": "Catawba's"
}
]
}
]
}
}
My Classes
[Serializable]
public class Suggest
{
[SerializeField]
public string suggestWords { get; set; }
}
[Serializable]
public class Result
{
[SerializeField]
public string OriginalWord { get; set; }
[SerializeField]
public List<Suggest> suggests { get; set; }
}
[Serializable]
public class Response
{
[SerializeField]
public int status { get; set; }
[SerializeField]
public bool isSuccess { get; set; }
[SerializeField]
public string message { get; set; }
[SerializeField]
public List<Result> result { get; set; }
}
Im Deserializing like this
Response response = JsonUtility.FromJson<Response>(jsonString);
Above every class there got to be [System.Serializable] this is because UnityEngine has its own implementation of Serializable so you got to indicate its the System's that you want to use rather then Unity's. You also dont need to have [SerializeField] since this is if you want to show the property in Unity's inspection window and since this will not go onto any gameobject you dont need this. You just got to make it public.
Also in the class public class Response if you want json to map correctly you wouldnt use public List<Result> result { get; set; }, it would have to be named response and it will have to be 1 object not a list. So you can create a class called Results and have it have a list variable called result and it will be a list of type Result (no s). and in the result it would have the OriginalWord and a list of Suggest called suggests
Moreover, you must have a constructor for each class for it to work. So it would look like this:
[System.Serializable]
public class Suggest
{
public string suggestWords;
public Suggest(string suggestWords)
{
this.suggestWords = suggestWords;
}
}
[System.Serializable]
public class Result
{
public string OriginalWord;
public List<Suggest> suggests;
public Result(string OriginalWord, List<Suggest> suggests)
{
this.OriginalWord = OriginalWord;
this.suggests = suggests;
}
}
[System.Serializable]
public class Results
{
public List<Result> result;
public Results(List<Result> result)
{
this.result = result;
}
}
[System.Serializable]
public class Response
{
public int status;
public bool isSuccess;
public string message;
public Results response;
public Response (int status, bool isSuccess, string message, Result response)
{
this.status = status;
this.isSuccess = isSuccess;
this.message = message;
this.response = response;
}
}
Hello i want to deserialize a class which contains a string, a bool and a List<[mystructtype>;When using JsonConvert.Deserialize<[myclass]> it deserializes the string and the bool correctly but not the List<[Struct]>.I have also changed the List<struct> with an array of structs.Both the class container and the struct are marked with Serializeable and i do not understand where the problem is.
Can anyone help me?
Struct
[Serializable]
public struct Status
{
//identifiers
public long playerId { get; set; }
public long groupId { get; set; }
public int type { get; set; }
}
Class Container
[Serializable]
class GatewayDeviceResponse
{
public bool status { get; set; } //gets deserialized good
public string message { get; set; } //gets deserialized good
public Status[] data { get; set; } // all members are defaults
}
Deserialization
IRestResponse response = client.Execute(request);
string result = Encoding.UTF8.GetString(response.RawBytes);
GatewayDeviceResponse resp = JsonConvert.DeserializeObject<GatewayDeviceResponse>(result);
return resp.data.ToList();
P.S The string is a response from a webserver,and i am using RestSharp for creating the server request and getting the response.The thing is the response string is good.The class is deserialized good excluding the collection.
What could the problem be?
P.S
The string response from the server i get is :
"{
\"status\":true,
\"message\":\"ok\",
\"data\":[
{
\"status\":{
\"playerId\":59,
\"groupId\":26,
\"type\":2,
\"deviceId\":\"abababa",
\"groupName\":\"srl\",
\"playerName\":\"Adrian\"
}
},
{
\"status\":{
\"playerId\":25,
\"groupId\":26,
\"type\":1,
\"deviceId\":\"lalal\",
\"groupName\":\"srl\",
\"playerName\":\"Alex\"
}
}
]
}"
The Status[] array elements are not supposed to be fully filled by the server response , just the 3 fields i have posted in the POCO/
I wrote a unit test as below and it passes and correctly deserialized with restsharp. Can you replace your response string and classes to check unit test still pass?
May be your class representation is not fit for your response. Take a little help from http://json2csharp.com/ and check your classes represents your json correctly.
[Test]
public void Can_Deserialize_Struct()
{
var data = "{ \"myList\":[{\"name\": \"test1234\"}] }";
JsonDeserializer json = new JsonDeserializer();
var output = json.Deserialize<MyTest>(new RestResponse { Content = data });
Assert.NotNull(output);
}
class MyTest
{
public List<MyStruct> MyList { get; set; }
}
struct MyStruct
{
public String name { get; set; }
}
According to your response string, your c# classes should represent your json as below :
public class Status
{
public int playerId { get; set; }
public int groupId { get; set; }
public int type { get; set; }
public string deviceId { get; set; }
public string groupName { get; set; }
public string playerName { get; set; }
}
public class StatusData
{
public Status status { get; set; }
}
public class GatewayDeviceResponse
{
public bool status { get; set; }
public string message { get; set; }
public List<StatusData> data { get; set; }
}
It does not related with type struct or class. You need to add another class in front of your status representation class. Because it starts as a json object in your response string.
My Activity code is:
private void MClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
string json = Encoding.UTF8.GetString(e.Result);
var Details = JsonConvert.DeserializeObject(json);
}
My doctor.cs class code is:
namespace App12
{
public class Doctor
{
public string DoctorId { get; set; }
public string doctorName { get; set; }
public string specialityId { get; set; }
public string experiance { get; set; }
public string fee { get; set; }
}
public class RootObject
{
public Doctor doctor { get; set; }
}
}
JSON array is:
{
"0": {
"DoctorId": "1",
"doctorName": "DR.Rama",
"specialityId": "1",
"experiance": "5 years",
"fee": "300rs"
}
}
I am trying to show this in textview but it gives me an error:
System.InvalidCastException: Specified cast is not valid.
You have two problems here.
Your class structure doesn't quite match up with the shape of the JSON data. This JSON isn't technically an array either; it's a dictionary. You need to deserialize into a Dictionary<string, Doctor>.
When calling JsonConvert.DeserializeObject you need to specify a type parameter. If you don't, the return type will be JObject. This may be the cause of the InvalidCastException.
Try it like this:
var dict = JsonConvert.DeserializeObject<Dictionary<string, Doctor>>(json);
From there you can loop through the doctors like this:
foreach (var doctor in dict.Values)
{
textView.Append(doctor.doctorName);
}
how can i parse this json response and create c# object
{"Response":"valid","Files":{"0":{"FileURL":"htp:\/\/somedomain.com\/1.exe","FileVersion":1},"1":{"FileURL":"htp:\/\/somedomain.com\/1.exe","FileVersion":2}}}
i have c# class
public class Files
{
public string fileURL;
public string fileVersion;
}
WebClient wc=new WebClient();
string code=wc.DownloadString("http://somedomain.com/GetLatestFiles.php");
List<Files> f=ParseJson(code);
how can i parse this json please help. I need to implement ParseJson which will return files list or can i deserialize this response to c# class?
Thankyou
Edit implemented some solution but its very slow?
public class LatestFile
{
public string fileURL;
public string fileVersion;
}
private List<LatestFile> ParseJson(string code)
{
List<LatestFile> files = new List<LatestFile>();
dynamic jObj = JsonConvert.DeserializeObject(code);
foreach (var child in jObj.Files.Children())
{
string index = child.Name;
string url = child.First.FileURL.Value;
string version = child.First.FileVersion.Value.ToString();
LatestFile f = new LatestFile();
f.fileURL = url;
f.fileVersion = version;
files.Add(f);
}
return files;
}
Based on #Brian Rogers answer below i am able to implement the generic solution working fast and efficiently.Thanks
https://dotnetfiddle.net/tC0Dws
Try defining your classes like this:
public class RootObject
{
public string Response { get; set; }
public Dictionary<string, LatestFile> Files { get; set; }
}
public class LatestFile
{
public string FileURL { get; set; }
public string FileVersion { get; set; }
}
And make your helper method like this:
private List<LatestFile> ParseJson(string json)
{
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
return obj.Files.Values.ToList();
}
Fiddle: https://dotnetfiddle.net/vpre5H
According to the JSON you provided you have three different objects there. First with Response and Files fields. Second - it looks like it's intended to be a collection but with current implementation it's an object - with fields 0 and 1. And third one with fields FileURL and FileVersion.
You can use DataContractJsonSerializer which is available starting from .Net 4.5. It's in System.Runtime.Serialization.Json namespace.
To parse your JSON you need following data structure:
[DataContract]
public class JsonResponse
{
[DataMember(Name = "Response")]
public string Response { get; set; }
[DataMember(Name = "Files")]
public Files Files { get; set; }
}
[DataContract]
public class Files
{
[DataMember(Name = "0")]
public MyFile Frst { get; set; }
[DataMember(Name = "1")]
public MyFile Scnd { get; set; }
}
[DataContract]
public class MyFile
{
[DataMember(Name = "FileURL")]
public string FileURL { get; set; }
[DataMember(Name = "FileVersion")]
public int FileVersion { get; set; }
}
To make testing easier I'm using your sample as a string but you can easily use URL or a Stream:
static string json = #"
{
""Response"":""valid"",
""Files"":
{
""0"":
{
""FileURL"":""htp:\/\/somedomain.com\/1.exe"",""FileVersion"":""1""
},
""1"":
{
""FileURL"":""htp:\/\/somedomain.com\/1.exe"",""FileVersion"":""2""
}
}
}";
static void Main(string[] args)
{
var serializer = new DataContractJsonSerializer(typeof(JsonResponse));
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(JsonResponse));
using (MemoryStream ms = new MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(json)))
{
JsonResponse response = (JsonResponse)js.ReadObject(ms);
}
}
And that's the result:
iam using a RequestClass with the Route anotation to call a Json-Client POST method.
Now, while the paramters are structured like this
public class GetTicketRequest: IReturn<JsonObject>
{
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
}
The BackendAPI needs them to be nesten in "data" in the json request, so more like
{
"data":[
{"cartid":123,
"priceId":11}]
}
Is there any way to transfrom the request object for the body before calling
JsonServiceClient _restClient = new JsonServiceClient(baseUrl);
JsonObject oneResponse = _restClient.Post(options);
This solution is useful where many DTOs require to be wrapped & converted, and is highly reusable, with no changes to your existing DTOs.
You can convert the requests of the JsonServiceClient by overriding the methods that handle preparing the requests for sending. Which means implementing your own extended JsonServiceClient as given below.
If you want to do this for all verbs then you override it's Send<TResponse> methods (otherwise, if it's just for POST then uncomment the commented out code, and remove the Send methods).
public class MyJsonServiceClient : JsonServiceClient
{
public Dictionary<Type, Func<object, object>> DtoConverters = new Dictionary<Type, Func<object, object>>();
public MyJsonServiceClient() {}
public MyJsonServiceClient(string baseUri) : base(baseUri) {}
public MyJsonServiceClient(string syncReplyBaseUri, string asyncOneWayBaseUri) : base(syncReplyBaseUri, asyncOneWayBaseUri) {}
public override TResponse Send<TResponse>(object request)
{
return base.Send<TResponse>(ConvertRequest(request));
}
public override TResponse Send<TResponse>(string httpMethod, string relativeOrAbsoluteUrl, object request)
{
return base.Send<TResponse>(httpMethod, relativeOrAbsoluteUrl, ConvertRequest(request));
}
/*
public override TResponse Post<TResponse>(string relativeOrAbsoluteUrl, object requestDto)
{
return base.Post(relativeOrAbsoluteUrl, ConvertRequest(requestDto));
}
*/
object ConvertRequest(object request)
{
Type dtoType = request.GetType();
return (DtoConverters.ContainsKey(dtoType)) ? DtoConverters[dtoType](request) : request;
}
}
Usage:
So given this DTO:
[Route("/test", "POST")]
public class TicketRequest : IReturnVoid
{
public string CartId { get; set; }
public string PriceId { get; set; }
}
You simply add the converter:
var client = new MyJsonServiceClient("http://localhost:9000");
// Simple converter for TicketRequest
client.DtoConverters.Add(typeof(TicketRequest), dto => {
var d = (TicketRequest)dto;
return new {
data = new {
CartId = d.CartId.ToInt(),
PriceId = d.PriceId.ToInt()
}
};
});
client.Post(new TicketRequest { CartId = "123", PriceId = "456" });
i solved this issue using a typed data property
public class GetTicketRequest: IReturn<JsonObject>
{
public class TicketCreateData
{
public int priceId {
get;
set;
}
}
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
public List<TicketCreateData> data {
get {
var list = new List<TicketCreateData>();
list.Add(new TicketCreateData {
priceId = this.PriceId.ToInt()
});
return list;
}
set {
data = value;
}
}
}
To notes on this:
if neede, use DataContract/DataMember(Name="") to rename fields or only do partial serializing
Do never use structs for, like in this case, the data class - they are not serializeable at all
in my spefici case data even needs to be an array, thats why i used the list