3

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?

directedition
  • 11,145
  • 18
  • 58
  • 79
  • Set the attribute dynamically at runtime, using reflection. See [Change Attribute's parameter at runtime](http://stackoverflow.com/questions/51269/change-attributes-parameter-at-runtime) – mason Apr 17 '14 at 20:28

2 Answers2

3

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"
Tim S.
  • 55,448
  • 7
  • 96
  • 122
0

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.

Ken Lassesen
  • 125
  • 9
  • why would someone click on that url name ? – Drew Jan 06 '16 at 00:12
  • Please include the relevant information in your answer here. Also, when linking to your own blog, please say that it is your blog. Otherwise it may be considered as spam. See: [How to not be a spammer](https://stackoverflow.com/help/promotion) –  Jan 06 '16 at 00:23
  • Welcome to Stack Overflow! Please read the guidelines for linking to your personal blog in your answers at http://meta.stackexchange.com/questions/141589. To fit these guidelines, this answer should be updated so users can solve the question without clicking through to the blog post. Also, make sure you don't get into a habit of always linking to your blog. – josliber Jan 10 '16 at 12:29