It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Sprint field value REST API

Maarten Cautreels Community Leader Aug 25, 2013

When trying to get the details of an issue through the REST API the response for the Sprint looks something like this:

  • customfield_10007:[
    • "com.atlassian.greenhopper.service.sprint.Sprint@a29f07[rapidViewId=<null>,state=CLOSED,name=NORD - Sprint 42,startDate=2013-07-29T06:47:00.000+02:00,endDate=2013-08-11T20:47:00.000+02:00,completeDate=2013-08-14T15:31:33.157+02:00,id=107]",
    • "com.atlassian.greenhopper.service.sprint.Sprint@769133[rapidViewId=<null>,state=ACTIVE,name=NORD - Sprint 43,startDate=2013-08-14T15:32:47.322+02:00,endDate=2013-08-23T15:32:47.322+02:00,completeDate=<null>,id=117]"
    ],

It looks like toString of the Sprint class which isn't very easy to parse/read with an application. Is their a way to simple get the Sprint Name or id returned through the REST API. It's necessary to be able to retrieve the Sprint value in an internal tool for our QA Team (Spira Test).

On the other side, using toString in the REST API output doesn't seem like a good idea to me ...

Thanks,

Maarten

7 answers

1 accepted

2 votes
Answer accepted
Stef Klaassen Nov 17, 2017

I was having the same issue for a small tool I was developing in which I needed the sprint name. Since I was using Jackson to unmarshal my JIRA response, I ended up writing a custom deserializer: 

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import static java.util.stream.Collectors.toList;

public class SprintNamesExtractingDeserializer extends JsonDeserializer<Collection> {

private static final String OPEN_ARRAY_CHARACTER = "\\[";
private static final String CLOSE_ARRAY_CHARACTER = "]";
private static final String COMMA = ",";
private static final String EQUALS_SIGN = "=";
private static final String NAME_PROPERTY = "name";

public SprintNamesExtractingDeserializer() {
}

@Override
public Collection deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
TypeReference<Collection<String>> typedCollection = new TypeReference<Collection<String>>() {
};
Collection<String> sprints = jsonParser.readValueAs(typedCollection);
return sprints.stream()
.map(extractSprintName())
.collect(toList());
}

private Function<String, String> extractSprintName() {
return sprintString -> {
String result = sprintString.split(OPEN_ARRAY_CHARACTER, 2)[1];
Map<String, String> sprintProperties = extractSprintProperties(result);

return sprintProperties.getOrDefault(NAME_PROPERTY, null);
};
}

private Map<String, String> extractSprintProperties(String result) {
int lastArrayClosure = result.lastIndexOf(CLOSE_ARRAY_CHARACTER);
result = result.substring(0, lastArrayClosure);
String[] propertiesArray = result.split(COMMA);
HashMap<String, String> properties = new HashMap<>();
for (String property: propertiesArray) {
String[] keyValueArray = property.split(EQUALS_SIGN);
if (keyValueArray.length == 1) {
properties.put(keyValueArray[0], null);
} else if (keyValueArray.length == 2) {
properties.put(keyValueArray[0], keyValueArray[1]);
}
// Else it's not a valid property
}
return properties;
}

}

Which can be used as: 

@JsonProperty("customfield_10400")
@JsonDeserialize(using = SprintNamesExtractingDeserializer.class, as=Collection.class)
public abstract Collection<String> getSprintNames();

 I'm not particularly proud of this solution, but it does the trick. 

Andris Vilde Jun 22, 2018

@Stef Klaassen, thank you! I used your method extractSprintProperties to get readable data from sprint string retrieved from the field.

No idea why would API return JSONArray with no way to cleanly cast it to array of sprints. I also need to get the state out of sprint and mark active one.

2 votes
Maarten Cautreels Community Leader Sep 11, 2013

No Answer has been found :-(

Sudhanshu Bhandari Mar 15, 2018

Can you please give me the rest call url to fetch the data which you have found havent even have that url to fetch that data for me . thanks!

1 vote
Dragica Soldo Dec 18, 2013

Any idea of one jar containing the mentioned class com.atlassian.greenhopper.service.sprint.Sprint
I assume the response can be parsed something like the following:

Field field = issue.getFieldByName("Sprint");
JSONArray fieldValue = (JSONArray) field.getValue();
com.atlassian.greenhopper.service.sprint.Sprint sprint = (Sprint) fieldValue.get(0);

I just can't find the particular class/jar.

Dragica Soldo Dec 18, 2013

Found it, but it looks too big to include, I think I'll go with parsing it as a String.

Jar info can be found at https://www.versioneye.com/java/com.atlassian.jira.plugins:jira-greenhopper-plugin/6.2

0 votes
Timothy Chin Community Leader Aug 25, 2013

It's not hard to parse that. The toString returns a JSON representation of that object. You just need to convert that String into a JSON object.

Maarten Cautreels Community Leader Sep 01, 2013

It's far from JSON ...

JSON would be something like this:

{
	rapidViewId: 1,
	state: "Closed",
	name: "NORD - Sprint 42",
	...
}

0 votes
Adrisson Floriano Nov 09, 2017

Up?

0 votes
Stef Klaassen Nov 17, 2017 • edited Nov 19, 2017

[ignore]Double-post because of spam filter not letting through my code example.[/ignore] 

0 votes
Pysis Aug 10, 2018 • edited

Haven't found a great way, but this works pretty well.  Using that Java class seems like it would match best, but honestly we shouldn't have to do this sort of parsing for a JSON REST API.

You can pipe that field through the `jq` utility this way to turn that rubbish Java serialization into desired JSON:

match("[\\\\w.]+?@\\\\w+?\\\\[(.*?)\\\\]").captures[0].string | split(",") | map(split("=") | {"key": .[0], "value": .[1]}) | from_entries

 

Suggest an answer

Log in or Sign up to answer
This widget could not be displayed.
This widget could not be displayed.
Community showcase
Published in Jira Software

Early Access: If you use Jenkins and Jira Software Cloud, you need to read this!

The Jira Software Cloud Team has been busy working on a simple, secure, and reliable way to integrate your build and deployment information from Jenkins with Jira Software Cloud. This means you don’t...

263 views 0 8
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you