JsonUtility.FromJson Cannot extract JSON data to string - json

I am trying to get data from a returned JSON result from REST API from my local host backend. I could get the value from name field but could not get the coord value. Are there any way to do so? Thanks!
The following is the results I got.
{
"coord" : {
"lon" : xxx.xxx,
"lat" : xx.xxxx
},
"weather" : [
{
"id" : 801,
"main" : "Clouds",
"description" : "few clouds",
"icon" : "02d"
}
],
"base" : "stations",
"main" : {
"temp":23.04,
"feels_like":22.89,
"temp_min":21.83,
"temp_max":24.52,
"pressure":916,
"humidity":57
},
"name" : "Ma Nam Wat"
}
My code:
public class GetMethod : MonoBehaviour
{
public WeatherInfo Info;
void GetData() => StartCoroutine(GetData_Coroutine() );
IEnumerator GetData_Coroutine()
{
string uri = "http://localhost:3000/api/weather/current?lat=22.426522&lon=114.234446&unit=metric";
using (UnityWebRequest request = UnityWebRequest.Get(uri))
{
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
Debug.Log(request.error);
else
Debug.Log(request.downloadHandler.text);
Info = JsonUtility.FromJson<WeatherInfo>(request.downloadHandler.text);
Debug.Log(Info.coord.lon.ToString());
}
}
}
[SerializeField]
public class WeatherInfo
{
public Coord coord;
public string name;
}
[SerializeField]
public class Coord
{
public float lon;
public float lat;
}

You confused the attribute [SerializeField] which is for serializing a non-public field with [System.Serializable] which is for marking a type serializable ;)
[Serializable]
public class WeatherInfo
{
public Coord coord;
public string name;
}
[Serializable]
public class Coord
{
public float lon;
public float lat;
}

Related

Using JsonUtility FromJson to deserialize JSON in Unity

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

.NET NewtonSoft JSON deserialize with different property name [duplicate]

how can I deserialize below json structure using newtonsoft json.net in .net.
{
"users" : {
"parentname":"test",
"100034" : {
"name" : "tom",
"state" : "WA",
"id" : "cedf-c56f-18a4-4b1"
},
"10045" : {
"name" : "steve",
"state" : "NY",
"id" : "ebb2-92bf-3062-7774"
},
"12345" : {
"name" : "mike",
"state" : "MA",
"id" : "fb60-b34f-6dc8-aaf7"
}
}
}
I tried below code but its not working. I got error 'Error converting value "test" to type 'ConsoleApplication2.User'. Path 'users.parentname', line 5, position 35.'
class Program
{
static void Main(string[] args)
{
string json = #"
{
""users"": {
""parentname"":""test"",
""10045"": {
""name"": ""steve"",
""state"": ""NY"",
""id"": ""ebb2-92bf-3062-7774""
}
}
}";
RootObject root = JsonConvert.DeserializeObject<RootObject>(json);
}
}
class RootObject
{
public string ParentName { get; set; }
public Dictionary<string, User> users { get; set; }
}
class User
{
public string name { get; set; }
public string state { get; set; }
public string id { get; set; }
public string ParentName { get; set; }
}
Please suggest.
You have a couple problems:
Your JSON has an extra level of nesting, with the root object containing a single property "users":
{
"users" : { ... }
}
Your data model needs to reflect this.
Your "users" object has a mixture of known and unknown property names. The question Deserialize json with known and unknown fields addresses a similar situation, however in your case your unknown properties always have a fixed schema and their values should be deserialized into a dictionary of POCOs -- specifically the User class. Therefore the answers there don't quite meet your needs, nor does the build-in functionality [JsonExtensionData].
The following converter allows for unknown properties to be deserialized into a typed container, rather than into an dictionary of arbitrary types:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public class JsonTypedExtensionDataAttribute : Attribute
{
}
public class TypedExtensionDataConverter<TObject> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(TObject).IsAssignableFrom(objectType);
}
JsonProperty GetExtensionJsonProperty(JsonObjectContract contract)
{
try
{
return contract.Properties.Where(p => p.AttributeProvider.GetAttributes(typeof(JsonTypedExtensionDataAttribute), false).Any()).Single();
}
catch (InvalidOperationException ex)
{
throw new JsonSerializationException(string.Format("Exactly one property with JsonTypedExtensionDataAttribute is required for type {0}", contract.UnderlyingType), ex);
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jObj = JObject.Load(reader);
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);
var extensionJsonProperty = GetExtensionJsonProperty(contract);
var extensionJProperty = (JProperty)null;
for (int i = jObj.Count - 1; i >= 0; i--)
{
var property = (JProperty)jObj.AsList()[i];
if (contract.Properties.GetClosestMatchProperty(property.Name) == null)
{
if (extensionJProperty == null)
{
extensionJProperty = new JProperty(extensionJsonProperty.PropertyName, new JObject());
jObj.Add(extensionJProperty);
}
((JObject)extensionJProperty.Value).Add(property.RemoveFromLowestPossibleParent());
}
}
var value = existingValue ?? contract.DefaultCreator();
using (var subReader = jObj.CreateReader())
serializer.Populate(subReader, value);
return value;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(value.GetType());
var extensionJsonProperty = GetExtensionJsonProperty(contract);
JObject jObj;
using (new PushValue<bool>(true, () => Disabled, (canWrite) => Disabled = canWrite))
{
jObj = JObject.FromObject(value, serializer);
}
var extensionValue = (jObj[extensionJsonProperty.PropertyName] as JObject).RemoveFromLowestPossibleParent();
if (extensionValue != null)
{
for (int i = extensionValue.Count - 1; i >= 0; i--)
{
var property = (JProperty)extensionValue.AsList()[i];
jObj.Add(property.RemoveFromLowestPossibleParent());
}
}
jObj.WriteTo(writer);
}
[ThreadStatic]
static bool disabled;
// Disables the converter in a thread-safe manner.
bool Disabled { get { return disabled; } set { disabled = value; } }
public override bool CanWrite { get { return !Disabled; } }
public override bool CanRead { get { return !Disabled; } }
}
public struct PushValue<T> : IDisposable
{
Action<T> setValue;
T oldValue;
public PushValue(T value, Func<T> getValue, Action<T> setValue)
{
if (getValue == null || setValue == null)
throw new ArgumentNullException();
this.setValue = setValue;
this.oldValue = getValue();
setValue(value);
}
#region IDisposable Members
// By using a disposable struct we avoid the overhead of allocating and freeing an instance of a finalizable class.
public void Dispose()
{
if (setValue != null)
setValue(oldValue);
}
#endregion
}
public static class JsonExtensions
{
public static TJToken RemoveFromLowestPossibleParent<TJToken>(this TJToken node) where TJToken : JToken
{
if (node == null)
return null;
var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
if (contained != null)
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (node.Parent is JProperty)
((JProperty)node.Parent).Value = null;
return node;
}
public static IList<JToken> AsList(this IList<JToken> container) { return container; }
}
Then use it in your classes as follows:
class RootObject
{
[JsonProperty("users")]
public Users Users { get; set; }
}
[JsonConverter(typeof(TypedExtensionDataConverter<Users>))]
class Users
{
public Users()
{
this.UserTable = new Dictionary<string, User>();
}
[JsonProperty("parentname")]
public string ParentName { get; set; }
[JsonTypedExtensionData]
public Dictionary<string, User> UserTable { get; set; }
}
class User
{
public string name { get; set; }
public string state { get; set; }
public string id { get; set; }
}
I wrote the converter in a fairly general way so it can be reused. A converter that is hardcoded for the Users type would require less code.
Your Json has to look like this:
{
"ParentName":"test",
"users":{
"10045":{
"name":"steve",
"state":"NY",
"id":"ebb2-92bf-3062-7774",
"ParentName":"someOtherName"
}
}
}
In order to deserialize it with your given class structure:
class RootObject
{
public string ParentName { get; set; }
public Dictionary<string, User> users { get; set; }
}
class User
{
public string name { get; set; }
public string state { get; set; }
public string id { get; set; }
public string ParentName { get; set; }
}
Now you can deserialize the Json string with:
var root = JsonConvert.DeserializeObject<RootObject>(json);

Newtonsoft.Json Parsing an Object with Changing Type [duplicate]

This question already has answers here:
How to handle both a single item and an array for the same property using JSON.net
(9 answers)
Closed 2 years ago.
I'm working on writing a .Net Standard library for working with the UptimeRobot API. I've found an endpoint that sometimes returns an array of int and sometimes returns a single 0.
The field I'm working with is monitors.
{
"stat": "ok",
"pagination": {
"offset": 0,
"limit": 50,
"total": 2
},
"psps": [
{
"id": 2345678,
"friendly_name": "Full Status",
"monitors": 0,
"sort": 1,
"status": 1,
"standard_url": "https://stats.uptimerobot.com/xxxxxx",
"custom_url": ""
},
{
"id": 123456,
"friendly_name": "Filtered Status",
"monitors": [
783210435,
783210481
],
"sort": 1,
"status": 1,
"standard_url": "https://stats.uptimerobot.com/xxxxxx",
"custom_url": ""
}
]
}
This is my model:
using Newtonsoft.Json;
using System.Collections.Generic;
using SharpenUp.Common.Types;
using System.Diagnostics.CodeAnalysis;
namespace SharpenUp.Common.Models.PublicStatusPages
{
public class PublicStatusPage
{
[ExcludeFromCodeCoverage]
[JsonProperty( PropertyName = "id" )]
public int Id { get; set; }
[JsonProperty( PropertyName = "friendly_name" )]
public string Name { get; set; }
[JsonProperty( PropertyName = "monitors" )]
public List<int> Monitors { get; set; }
[JsonProperty( PropertyName = "sort" )]
public int Sort { get; set; }
[JsonProperty( PropertyName = "status" )]
public PublicStatusPageStatusType Status { get; set; }
[JsonProperty( PropertyName = "standard_url" )]
public string StandardURL { get; set; }
[JsonProperty( PropertyName = "custom_url" )]
public string CustomURL { get; set; }
}
}
The Monitors object will parse if I limit my query to only the result with the array, but fails if I try to bring in the other.
Any ideas? I'm not even 100% certain what wording to use to try and figure this out.
You could use a Converter which converts cases where there is only a single item to List. For example, considering the following converter.
class SingleOrArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<T>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T> { token.ToObject<T>() };
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
You could now decorate your Monitors property with JsonConverter attribute as
[JsonConverter(typeof(SingleOrArrayConverter<int>))]
[JsonProperty( PropertyName = "monitors" )]
public List<int> Monitors { get; set; }
This would allow you to deserialize your Json correctly.
Sample Output

Validating structure of Json object in WCF Rest Service

I have written a WCF Rest Service, where in POST method Json Object is received as StudentDetails. Now i want to validate its structure that it should not contain extra fields/information than the specified fields.
Below is my service(ServiceContract)
namespace RestService
{
[ServiceContract]
public interface IRestService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/SaveStudent", RequestFormat =WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string SaveStudent(StudentDetails studentDetails);
}
[Serializable]
public class WebServiceDictionary : ISerializable
{
public Dictionary<string, string> Entries { get; }
public WebServiceDictionary()
{
Entries = new Dictionary<string, string>();
}
public WebServiceDictionary(SerializationInfo info, StreamingContext context)
{
Entries = new Dictionary<string, string>();
foreach (var entry in info)
Entries.Add(entry.Name, entry.Value.ToString());
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (var entry in Entries)
info.AddValue(entry.Key, entry.Value);
}
}
[DataContract]
public class StudentDetails
{
[DataMember]
public WebServiceDictionary StudentDetail { get; set; }
}
}
This is implementation of Service
namespace RestService
{
public class RestService : IRestService
{
public string SaveStudent(StudentDetails studentDetails)
{
SqlHelper sql = new SqlHelper();
sql.OpenConnection();
WebServiceDictionary student = studentDetails.StudentDetail;
if (student.Entries.Keys.Count != 3)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.BadRequest;
return null;
}
sql.SaveJson(student.Entries["Name"], student.Entries["Address"], int.Parse(student.Entries["Grade"]));
sql.CloseConnection();
return "Passed";
}
}
}
So the Structure of Json should be
{
"StudentDetail" :
{
"Name" : "ABC", "Address" : "ABC", "Grade":"10"
}
}
I have put checks for not letting the request accepted when there is/are some fields are missing and it is working fine. Now i want that when Json data contains one or more extra information, the request should fail(BadRequest). For example if Json object is:
{
"StudentDetail" :
{
"Name" : "ABC", "Address" : "ABC", "Grade":"10", "Extra" : "Item"
}
}
As Extra item is present so it should fail(BadRequest).
And also
{
"StudentDetail" :
{
"Name" : "ABC", "Address" : "ABC", "Grade":"10"
},
"New" : { "key" : "value" }
}
As extra "New" item is introduced so it should fail(BadRequest).
Please help me.
Thanks
unfortunately you cant do this with wcf. in web api you simply can use dynamic object and validate the input. but in wcf you have to use an object like this:
[Serializable]
public class WebServiceDictionary : ISerializable
{
public Dictionary<string, string> Entries { get; }
public WebServiceDictionary()
{
Entries = new Dictionary<string, string>();
}
public WebServiceDictionary(SerializationInfo info, StreamingContext context)
{
Entries = new Dictionary<string, string>();
foreach (var entry in info)
Entries.Add(entry.Name, entry.Value.ToString());
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (var entry in Entries)
info.AddValue(entry.Key, entry.Value);
}
}
then your input will be like this:
[DataContract]
public class StudentDetails
{
[DataMember]
public WebServiceDictionar StudentDetail { get; set; }
}
}
now you can access to the StudentDetail like this:
StudentDetail.Entries[Name]
and then validate it.
at first you can get all the keys in your dictionary like this:
var keys=Entries.Keys;
then you can validate them like this:
if(keys.length!=3)
//its not valid
if(!keys.contain("Address"))
//its not valid
.
.
.

deserialize dataset in xamarin forms

How can you decrypt/ deserialize dataset. here is what i am getting from the web service. I am new to xamarin forms. Thanks in advance. i tried this json2csharp.com to convert, but got an error because it can convert datatable to csharp but not datasets.
[
[
{
"bit_HasError":false,
"vchar_ErrorMsg":""
}
],
[
{
"int_SurveyQuestionID":1,
"vchar_Description":"we",
"vchar_Instruction":"Question Instruction",
"int_AnswerType":1
},
{
"int_SurveyQuestionID":5,
"vchar_Description":"this is the question 2",
"vchar_Instruction":null,
"int_AnswerType":2
}
],
[
{
"int_SurveyQuestionID":1,
"vchar_Option":"option1"
},
{
"int_SurveyQuestionID":5,
"vchar_Option":"answer1"
},
{
"int_SurveyQuestionID":5,
"vchar_Option":"answer2"
},
{
"int_SurveyQuestionID":5,
"vchar_Option":"answer3"
},
{
"int_SurveyQuestionID":1,
"vchar_Option":"optionn2"
}
]
]
Using https://app.quicktype.io/ it is quite easy to get started, just copy paste your json in there, here is the result:
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using QuickType;
//
// var prject = Prject.FromJson(jsonString);
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class Prject
{
[JsonProperty("bit_HasError", NullValueHandling = NullValueHandling.Ignore)]
public bool? BitHasError { get; set; }
[JsonProperty("vchar_ErrorMsg", NullValueHandling = NullValueHandling.Ignore)]
public string VcharErrorMsg { get; set; }
[JsonProperty("int_SurveyQuestionID", NullValueHandling = NullValueHandling.Ignore)]
public long? IntSurveyQuestionId { get; set; }
[JsonProperty("vchar_Description", NullValueHandling = NullValueHandling.Ignore)]
public string VcharDescription { get; set; }
[JsonProperty("vchar_Instruction")]
public string VcharInstruction { get; set; }
[JsonProperty("int_AnswerType", NullValueHandling = NullValueHandling.Ignore)]
public long? IntAnswerType { get; set; }
[JsonProperty("vchar_Option", NullValueHandling = NullValueHandling.Ignore)]
public string VcharOption { get; set; }
}
public partial class Prject
{
public static List<List<Prject>> FromJson(string json) => JsonConvert.DeserializeObject<List<List<Prject>>>(json, QuickType.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this List<List<Prject>> self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}
P.S.: Please note that you have to modify the class names.