json - http://pastebin.com/Ss1YZsLK
I need to get market_hash_name values to list. I can receive first value so far:
using (WebClient webClient = new System.Net.WebClient()) {
WebClient web = new WebClient();
var json = web.DownloadString(">JSON LINK<");
Desc data = JsonConvert.DeserializeObject<Desc>(json);
Console.WriteLine(data.rgDescriptions.something.market_hash_name);
}
public class Desc {
public Something rgDescriptions { get; set; }
}
public class Something {
[JsonProperty("822948188_338584038")]
public Name something { get; set; }
}
public class Name {
public string market_hash_name { get; set; }
}
How can I get all if them?
Since there is no array inside the rgDescriptions but some randomly named looking properties I think you would need a custom JsonConverter. The following console application seems to be working and displaying the market_hash_names correctly:
class Program
{
static void Main(string[] args)
{
string json = File.ReadAllText("Sample.json");
Desc result = JsonConvert.DeserializeObject<Desc>(json);
result.rgDescriptions.ForEach(s => Console.WriteLine(s.market_hash_name));
Console.ReadLine();
}
}
public class Desc
{
[JsonConverter(typeof(DescConverter))]
public List<Something> rgDescriptions { get; set; }
}
public class Something
{
public string appid { get; set; }
public string classid { get; set; }
public string market_hash_name { get; set; }
}
class DescConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Something[]);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var descriptions = serializer.Deserialize<JObject>(reader);
var result = new List<Something>();
foreach (JProperty property in descriptions.Properties())
{
var something = property.Value.ToObject<Something>();
result.Add(something);
}
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Output:
Genuine Tactics Pin
Silver Operation Breakout Coin
Operation Phoenix Challenge Coin
Operation Bravo Challenge Coin
Related
we have our C# class as below
public class PrimaryContact
{
public string PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
we need to serialise to the json object as
"primaryContact": {
"prefixTitle": {
"value": "mrs"
},
"surName": "abcd",
"givenName": "abcd"
}
Please note the prefixTitle is intended with value. for some selected attributes we need to serialize like this. Also, we need to read from JSON and deserialise into the class. Is there any generic best approach we can follow by decorating the elements so that we can achieve this result?
As you have tagged your question with json.net, you can do this by applying a custom JsonConverter to the "selected attributes" that should be nested inside a {"value" : ... } object when serialized.
First, define the following converter:
public class NestedValueConverter<T> : JsonConverter
{
class Value
{
public T value { get; set; }
}
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
switch (reader.MoveToContent().TokenType)
{
case JsonToken.Null:
return null;
default:
return serializer.Deserialize<Value>(reader).value;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, new Value { value = (T)value });
}
}
public static partial class JsonExtensions
{
public static JsonReader MoveToContent(this JsonReader reader)
{
if (reader.TokenType == JsonToken.None)
reader.Read();
while (reader.TokenType == JsonToken.Comment && reader.Read())
;
return reader;
}
}
Now, apply it the "selected attributes" of PrimaryContact as follows:
public class PrimaryContact
{
[JsonConverter(typeof(NestedValueConverter<string>))]
public string PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
And you will be able to deserialize and serialize as follows:
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
var root = JsonConvert.DeserializeObject<RootObject>(jsonString, settings);
var json2 = JsonConvert.SerializeObject(root, Formatting.Indented, settings);
Notes:
As the converter is intended to be applied directly using the attributes [JsonConverter(typeof(NestedValueConverter<...>))] or [JsonProperty(ItemConverterType = typeof(NestedValueConverter<...>))], CanConvert, which is only called when the converter is included in settings, is not implemented.
The converter is generic in case you need to nest non-string values.
Sample fiddle here.
Here Prefix Title Also a class not a string.
Here your class want to look like this.
public class PrimaryContact
{
public PrefixTitle prefixTitle{ get; set; }
public string surName{ get; set; }
public string givenName{ get; set; }
}
public class PrefixTitle {
public string value {get; set;}
}
Install Newtonsoft.json libraby file to your project : ->
Open Package manager console in Tools NuGet Package and paste it then hit enter.
Install-Package Newtonsoft.Json -Version 12.0.1
Convert a Class to Json :
string output = JsonConvert.SerializeObject(classname);
Convert a Json to Object :
Here object denotes a Class
Object output = JsonConvert.DeSerializeObject<object>(jsonString);
Here You can find optimized code you can use in your project directly :
public static string getJsonFromClass(object objectName){
return JsonConvert.SerializeObject(object);
}
public static T getObjectFromJson<T>(string jsonString){
T t = default(T);
try{
t = JsonConvert.DeSerializeObject<T>(classname);
}catch(Exception e){
Debug.WriteLine(e.Message);
}
return t;
}
You can use this Method to achieve your output by :
string jsonData = getJsonFromClass(Prefix);
string JsonString = "<here your json string>";
Prefix getObjectFromJson = getObjectFromJson<Prefix>(JsonString);
thats all ..
I hope this can help for you..
You can achieve this by changing your model like:
public class PrimaryContact
{
public Prefix PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
public class Prefix
{
public string Value { get; set; }
}
Then
Newton.Json.JsonConvert.DeserializeObject<PrimaryContact>();
You need to write a custom serializer for your object. Here is an example to show how you can do this with extending JsonConverter and using some custom attribute to determine if your object/property should wrapped:
[WrapperAttribute(Key = "primaryContact")]
public class PrimaryContact
{
[WrapperAttribute(Key= "prefixTitle")]
public string PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
public class WrapperAttribute : Attribute
{
public string Key { get; set; }
}
public class WrapperSerializer : JsonConverter<PrimaryContact>
{
public override void WriteJson(JsonWriter writer, PrimaryContact value, JsonSerializer serializer)
{
Type type = value.GetType();
JObject root = new JObject();
foreach (var property in type.GetAllProperties())
{
if (property.HasAttribute<WrapperAttribute>())
{
JProperty wrappedProperty = new JProperty(property.GetAttribute<WrapperAttribute>().Key);
JObject wrappedChild = new JObject();
wrappedProperty.Value = wrappedChild;
JProperty wrappedChildProperty = new JProperty("value");
wrappedChildProperty.Value = JToken.FromObject(property.GetValue(value));
wrappedChild.Add(wrappedChildProperty);
root.Add(wrappedProperty);
}
else
{
var childProperty = new JProperty(property.Name);
childProperty.Value = JToken.FromObject(property.GetValue(value));
root.Add(childProperty);
}
}
if (type.HasAttribute<WrapperAttribute>())
{
JObject wrappedRoot = new JObject();
var wrappedProperty = new JProperty(type.GetAttribute<WrapperAttribute>().Key);
wrappedProperty.Value = root;
wrappedRoot.Add(wrappedProperty);
wrappedRoot.WriteTo(writer);
}
else
{
root.WriteTo(writer);
}
}
public override PrimaryContact ReadJson(JsonReader reader, Type objectType, PrimaryContact existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
in main :
PrimaryContact contact = new PrimaryContact();
contact.GivenName = "test name";
contact.PrefixTitle = "test title";
contact.SurName = "test surname";
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new WrapperSerializer());
var serialized = JsonConvert.SerializeObject(contact, settings);
output :
{
"primaryContact": {
"prefixTitle": {
"value": "test title"
},
"SurName": "test surname",
"GivenName": "test name"
}
}
I am deserializing some JSON endpoints to C# Objects via JArray.Parse() and have come across a schema I'm not sure how to handle. The nUnavailResReasonsMap Object below has a dynamic number of name/value pairs; all of the name values will be integers:
{
"id": "Customer Service",
"operation": "UPDATE",
"VoiceIAQStats": {
"id": 139,
"esdId": 139,
...
"nUnavailResources": 2,
"nUnavailResReasonsMap": {
"4": 1,
"9": 1
},
"nWorkResources": 0,
"nSelectedResources": 0,
...
"nSLAPercentageHighThreshold": 0
}
}
And here are my C# Objects:
//Root Level
public class QueueStats
{
public string Id { get; set; }
public string Operation { get; set; }
public VoiceIaqStats VoiceIaqStats { get ; set ; }
}
public class VoiceIaqStats
{
public int Id { get; set; }
public int EsdId { get; set; }
...
public int NUnavailResources { get; set; }
public NUnavailResReasonsMaps NUnavailResReasonsMap { get ; set ; }
public int NWorkResources { get; set; }
public int NSelectedResources { get; set; }
...
public int NSlaPercentageHighThreshold { get; set; }
}
[JsonConverter( typeof( QueueStatsConverter))]
public class NUnavailResReasonsMaps
{
public Dictionary<string ,int > NUnavailResReasonsMap { get; set; }
}
Per another SO Post, I have setup the below Json Converter, which is getting called but I'm not sure how to get the values into the Dictionary defined above.
public class QueueStatsConverter : JsonConverter
{
public override bool CanConvert( Type objectType)
{
return objectType.IsClass;
}
public override bool CanWrite => false;
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var instance = objectType.GetConstructor(Type .EmptyTypes)?.Invoke(null);
var props = objectType.GetProperties();
var jo = JObject.Load(reader);
foreach ( var jp in jo.Properties())
{
//I can see the properties, but how do I add them to my existing dictionary?
}
return instance;
}
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Is there a way to make this work or do I need to change my approach?
You don't need a special converter at all, just remove the NUnavailResReasonsMaps class and use a Dictionary<int, int> instead:
public class VoiceIaqStats
{
//snip
public Dictionary<int, int> NUnavailResReasonsMap { get; set; }
//snip
}
And the conversion will work out of the box:
var result = JsonConvert.DeserializeObject<QueueStats>(json);
I have a simple GitHub payload incoming to my ASP.NET Core application and I would like to know how can I map the payload I receive to my DTO.
Example DTO
public class GithubPayload
{
public string Action { get; set; } // action
public string Name { get; set; } // pull_request.title
}
Example payload
{
"action": "deleted",
"pull_request": {
"title": "Fix button"
}
}
You can use JsonProperty attribute on Action and a custom converter on the Name that can interpret nested properties. check Json.Net's JsonConverter
public class GithubPayload {
[JsonProperty("action")]
public string Action { get; set; }
[JsonConverter(typeof(NestedConverter), "pull_request.title")]
public string Name { get; set; }
}
Where NestedConverter is a custom JsonConverter that will read a nested property
public class NestedConverter : JsonConverter {
private readonly string path;
public NestedConverter (string path) {
this.path = path;
}
//...to do
}
Update:
Using a JsonConverter for converting the payload itself actually works as well
public class GithubPayloadConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return objectType == typeof(GithubPayload);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
dynamic data = JObject.Load(reader);
var model = new GithubPayload {
Action = data.action,
Name = data.pull_request.title
};
return model;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
}
and decorating the class itself
[JsonConverter(typeof(GithubPayloadConverter))]
public class GithubPayload {
public string Action { get; set; }
public string Name { get; set; }
}
Deserialization is simply
string json = #"{ 'action': 'deleted', 'pull_request': { 'title': 'Fix button' } }";
var payload = JsonConvert.DeserializeObject<GithubPayload>(json);
Just an idea:
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json;
using System.IO;
namespace WebApplication1
{
public class Program
{
public class GithubPayload
{
public string Action { get; set; } // action
public string Name { get; set; } // pull_request.title
}
public static void Main(string[] args)
{
string json = #"{
""action"": ""deleted"",
""pull_request"": {
""title"": ""Fix button""
}
}";
dynamic obj = JsonConvert.DeserializeObject(json);
GithubPayload entity = new GithubPayload();
entity.Action = obj.action;
entity.Name = obj.pull_request.title;
..................
}
}
}
Tested this solution, it works.
I want to serialize/deserialize following classes into/from JSON:
public class Employee
{
string name;
Position position;
}
public class Position
{
string positionName;
int salary;
}
The tricky part is that I want to treat Position fields as Employee fields, so JSON would look like this:
{
"name": "John",
"positionName": "Manager",
"salary" : 1000
}
How to achieve this using Json.NET ?
You have either to deserialize it as anonymous object either (recommended ) implement a custom deserialization as stated here:
Merge two objects during serialization using json.net?
Please let us know if there any more questions.
Here's an example (you can find it in the provided link):
public class FlattenJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
return;
}
JObject o = (JObject)t;
writer.WriteStartObject();
WriteJson(writer, o);
writer.WriteEndObject();
}
private void WriteJson(JsonWriter writer, JObject value)
{
foreach (var p in value.Properties())
{
if (p.Value is JObject)
WriteJson(writer, (JObject)p.Value);
else
p.WriteTo(writer);
}
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return true; // works for any type
}
}
My solution is this
static void Main(string[] args)
{
Position p = new Position();
p.positionName = "Manager";
p.salary = 1000;
Employee e = new Employee();
e.name = "John";
e.position = p;
ResultJson r = new ResultJson();
r.name = e.name;
r.positionName = e.position.positionName;
r.salary = e.position.salary;
var result = JsonConvert.SerializeObject(r);
Console.WriteLine(result);
Console.ReadLine();
}
}
public class Employee
{
public string name { get; set; }
public Position position { get; set; }
}
public class Position
{
public string positionName { get; set; }
public int salary { get; set; }
}
public class ResultJson
{
public string name { get; set; }
public string positionName { get; set; }
public int salary { get; set; }
}
use seperate model for result
You can use this code with NewtonSoft.Json library
[JsonObject]
public class Employee
{
[JsonProperty("name")]
string name;
[JsonProperty("positionName")]
string positionName;
[JsonProperty("salary")]
int salary;
}
Use One class instead 2, or realize own parser
try in this way.
{
"name": "John",
"position":
[{
"positionName": "Manager",
"salary" : 1000
}]
}
I have a Web Api Controller like this one :
public IHttpActionResult Create(PaymentDTO Payment)
My DTOs are:
public class PaymentDTO
{
public int Id { get; set; }
public string type { get; set; }
public IEnumerable<TransactionDTO> Transactions { get; set; }
}
public class TransactionDTO
{
public int Id { get; set; }
public string Description { get; set; }
public string CreateTime { get; set; }
public string UpdateTime { get; set; }
}
public class SaleDTO : TransactionDTO
{
public string Total { get; set; }
public string Currency{ get; set; }
}
public class OrderDTO : TransactionDTO
{
public string State {get;set;}
}
I receive the following JSON formatted data :
{
"Type": "sale",
"Id": 101,
"transactions": [
{
"Total": "30.50",
"Currency": "USD",
"Description": "transaction description"
}
]
}
I want JSON.net to instantiate either a IEnumerable<SaleDTO> or IEnumerable<OrderDTO> based on the Type Property.
I could've used a custom type converter, but only if Type property was in TransactionDTO. But I want the Type property to be in the parent object (PaymentDTO)
Thank you in advance for your help.
You can do this with a custom JsonConverter on the PaymentDTO class:
public class PaymentDTOConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(PaymentDTO).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var obj = JObject.Load(reader);
var payment = (PaymentDTO)existingValue ?? new PaymentDTO();
// Extract the transactions.
var transactions = obj.Property("transactions") ?? obj.Property("Transactions");
if (transactions != null)
transactions.Remove();
// Populate the remaining regular properties.
using (var subReader = obj.CreateReader())
serializer.Populate(subReader, payment);
if (transactions != null)
{
// Deserialize the transactions list.
var type = PaymentDTO.GetTransactionDTOType(payment.type) ?? typeof(TransactionDTO);
using (var subReader = transactions.Value.CreateReader())
// Here we are taking advantage of array covariance.
payment.Transactions = (IEnumerable<TransactionDTO>)serializer.Deserialize(subReader, type.MakeArrayType());
}
return payment;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then apply it to your PaymentDTO class as follows:
[JsonConverter(typeof(PaymentDTOConverter))]
public class PaymentDTO
{
static Dictionary<string, Type> namesToTransactions;
static Dictionary<Type, string> transactionsToNames = new Dictionary<Type, string>
{
{ typeof(SaleDTO), "sale" },
{ typeof(OrderDTO), "order" },
};
static PaymentDTO()
{
namesToTransactions = transactionsToNames.ToDictionary(p => p.Value, p => p.Key);
}
public static string GetTransactionDTOTypeName<TTransactionDTO>() where TTransactionDTO : TransactionDTO
{
string name;
if (transactionsToNames.TryGetValue(typeof(TTransactionDTO), out name))
return name;
return null;
}
public static Type GetTransactionDTOType(string name)
{
Type type;
if (namesToTransactions.TryGetValue(name, out type))
return type;
return null;
}
public int Id { get; set; }
public string type { get; set; }
[JsonProperty("transactions")]
public IEnumerable<TransactionDTO> Transactions { get; set; }
}