Last active
June 11, 2021 07:12
-
-
Save lucd/cdd57a2602bd975ec0a6 to your computer and use it in GitHub Desktop.
This code shows how to specify a navigation path in the JsonProperty attribute. It will traverse the JSON node and obtain the desired value to according to the path. Example [JsonProperty(parent/child)] will map to the value "a" from the JSON { "parent":{ "child": "a"} }. http://stackoverflow.com/questions/35628318/deserialize-nested-json-to-a-f…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
using System; | |
using System.Linq; | |
using System.Reflection; | |
namespace ConsoleApplication1 | |
{ | |
class Program | |
{ | |
/// <summary> | |
/// This code shows how to specify a navigation path in the JsonProperty attribute. | |
/// It will traverse the JSON node and obtain the desired value to according to the path. | |
/// Example | |
/// [JsonProperty(parent/child)] will map to the value "a" from the JSON { "parent":{ "child": "a"} }. | |
/// </summary> | |
/// <param name="args"></param> | |
static void Main(string[] args) | |
{ | |
string s = @" | |
{ | |
""id"": 100, | |
""fields"":{ | |
""issuetype"": { | |
""name"": ""I am a Jira issue"" | |
} | |
} | |
}"; | |
var settings = new JsonSerializerSettings(); | |
settings.Converters.Add(new ConventionBasedConverter()); | |
var o = JsonConvert.DeserializeObject<JiraIssue>(s, settings); | |
Console.WriteLine("Id: " + o.Id); | |
Console.WriteLine("Type: " + o.Type); | |
} | |
} | |
[JsonObject] | |
public class JiraIssue | |
{ | |
[JsonProperty("id")] | |
public int Id { get; set; } | |
[JsonProperty("fields/issuetype/name")] | |
public string Type { get; set; } | |
} | |
/// <summary> | |
/// Custom converter that allows mapping a JSON value according to a navigation path. | |
/// Credits to: http://stackoverflow.com/users/3887840/amit-kumar-ghosh | |
/// </summary> | |
class ConventionBasedConverter : JsonConverter | |
{ | |
public override bool CanConvert(Type objectType) | |
{ | |
return typeof(JiraIssue).IsAssignableFrom(objectType); | |
} | |
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |
{ | |
var daat = JObject.Load(reader); | |
var issue = new JiraIssue(); | |
foreach (var prop in issue.GetType().GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance)) | |
{ | |
var attr = prop.GetCustomAttributes(false).FirstOrDefault(); | |
if (attr != null) | |
{ | |
var propName = ((JsonPropertyAttribute)attr).PropertyName; | |
if (!string.IsNullOrWhiteSpace(propName)) | |
{ | |
//split by the delimiter, and traverse recursevly according to the path | |
var conventions = propName.Split('/'); | |
object propValue = null; | |
JToken token = null; | |
for (var i = 0; i < conventions.Length; i++) | |
{ | |
if (token == null) | |
{ | |
token = daat[conventions[i]]; | |
} | |
else { | |
token = token[conventions[i]]; | |
} | |
if (token == null) | |
{ | |
//silent fail: exit the loop if the specified path was not found | |
break; | |
} | |
else | |
{ | |
//store the current value | |
if (token is JValue) | |
{ | |
propValue = ((JValue)token).Value; | |
} | |
} | |
} | |
if (propValue != null) | |
{ | |
//workaround for numeric values being automatically created as Int64 (long) objects. | |
if (propValue is long && prop.PropertyType == typeof(Int32)) | |
{ | |
prop.SetValue(issue, Convert.ToInt32(propValue)); | |
} | |
else | |
{ | |
prop.SetValue(issue, propValue); | |
} | |
} | |
} | |
} | |
} | |
return issue; | |
} | |
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |
{ | |
} | |
} | |
} |
What about a dynamic attributes :-
{"root":{ "787<--This attribute name is dynamic-->":"Value" }.... }
What about a dynamic attributes :-
{"root":{ "787<--This attribute name is dynamic-->":"Value" }.... }
What do you mean with this?
Thank you for this. I spent 20 minutes looking at answers on SO that danced around this simple solution.
@MinnowTman - thank you! That gist really helped me out.
I've posted a solution with classes support here (based on @MinnowTman code)
https://stackoverflow.com/a/67932675/4601817
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
SUPERBB!! Really helpful. Been search for solution yet this one is the best. Thank you!!