Question

To serialize an object to json using json.net, I need to create POCOs with attributes labled for each json property:

public class Priority
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("iconUrl")]
    public string IconUrl { get; set; }
}

I'm using this to interact with Jira's REST API, and it works well for all the standard fields. Unfortunately, custom fields are where things trip up. Custom fields don't have determined field names, and instead have numbers assigned to them. So if I have a "Resolution Type" custom field, the property won't be called "ResolutionType", but rather "customfield_10200".

I'm dealing with multiple deployments with the same custom fields, but they all have different field Ids. What I'd love to do is something like this:

[JsonProperty(ConfigurationManager.AppSettings["JiraResolutionTypeId"])]
public string ResolutionType{ get; set; }

But you can only have compile-time constants in attributes like that, so I can't dynamically set the id in that manner.

How can I get around this?

Was it helpful?

Solution

Using a custom contract resolver should let you do this pretty easily. Adding your own Attribute class lets you do it in a generic way.

// add attribute so this only targets properties, or whatever you want
public class JiraAttribute : Attribute
{
    public string LookupId { get; private set; }
    public JiraAttribute(string lookupId)
    {
        this.LookupId = lookupId;
    }
}
public class JiraContractResolver : DefaultContractResolver
{
    public static readonly JiraContractResolver Instance = new JiraContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        var attr = member.GetCustomAttributes(typeof(JiraAttribute), true).Cast<JiraAttribute>().ToList();
        if (attr != null && attr.Count > 0)
        {
            property.PropertyName = ConfigurationManager.AppSettings[attr[0].LookupId];
        }

        return property;
    }
}

// in a class
[Jira("JiraResolutionTypeId")]
public string ResolutionType { get; set; }

//e.g.
// ConfigurationManager.AppSettings["JiraResolutionTypeId"] == "customfield_10200"
var settings = new JsonSerializerSettings { ContractResolver = JiraContractResolver.Instance };
var s = JsonConvert.SerializeObject(new Priority { Id = "123", ResolutionType = "abc" }, settings);
// {"id":"123","name":null,"iconUrl":null,"customfield_10200":"abc"}
var d = JsonConvert.DeserializeObject<Priority>(s, settings);
// d.ResolutionType == "abc"

OTHER TIPS

There is another approach that is documented here. http://www.31a2ba2a-b718-11dc-8314-0800200c9a66.com/2016/01/a-simple-approach-to-getting-all-of.html

Get Json request, convert to XML, save in SQL Server, then use custom functions to extract whatever you need from the custom JIRA fields.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top