Skip to content

Commit b84c156

Browse files
committed
execution result to spec
graphql-java#473 - execution result to spec
1 parent dd739e5 commit b84c156

5 files changed

Lines changed: 110 additions & 12 deletions

File tree

‎src/main/java/graphql/ExecutionResult.java‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,34 @@
22

33

44
import java.util.List;
5+
import java.util.Map;
56

7+
/**
8+
* This simple value class represents the result of performing a graphql query.
9+
*/
610
@PublicApi
711
public interface ExecutionResult {
812

13+
/**
14+
* @param <T> allows type coercion
15+
*
16+
* @return the data in the result or null if there is none
17+
*/
918
<T> T getData();
1019

20+
/**
21+
* @return the errors that occurred during execution or empty list if there is none
22+
*/
1123
List<GraphQLError> getErrors();
1224

25+
/**
26+
* The graphql specification says that result of a call should be a map that follows certain rules on what items
27+
* should be present. Certain JSON serializers may or may interpret {@link ExecutionResult} to spec, so this method
28+
* is provided to produce a map that strictly follows the specification.
29+
*
30+
* See : <a href="http://facebook.github.io/graphql/#sec-Response-Format">http://facebook.github.io/graphql/#sec-Response-Format">http://facebook.github.io/graphql/#sec-Response-Format</a>
31+
*
32+
* @return a map of the result that strictly follows the spec
33+
*/
34+
Map<String, Object> toSpecification();
1335
}

‎src/main/java/graphql/ExecutionResultImpl.java‎

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,36 @@
33

44
import java.util.ArrayList;
55
import java.util.Collections;
6+
import java.util.LinkedHashMap;
67
import java.util.List;
8+
import java.util.Map;
79

810
@Internal
911
public class ExecutionResultImpl implements ExecutionResult {
1012

1113
private final List<GraphQLError> errors = new ArrayList<>();
12-
private Object data;
14+
private final Object data;
15+
private final transient boolean dataPresent;
1316

1417
public ExecutionResultImpl(GraphQLError error) {
15-
this(Collections.singletonList(error));
18+
this(false, null, Collections.singletonList(error));
1619
}
1720

1821
public ExecutionResultImpl(List<? extends GraphQLError> errors) {
19-
this(null, errors);
22+
this(false, null, errors);
2023
}
2124

2225
public ExecutionResultImpl(Object data, List<? extends GraphQLError> errors) {
26+
this(true, data, errors);
27+
}
28+
29+
private ExecutionResultImpl(boolean dataPresent, Object data, List<? extends GraphQLError> errors) {
30+
this.dataPresent = dataPresent;
2331
this.data = data;
2432

2533
if (errors != null && !errors.isEmpty()) {
2634
this.errors.addAll(errors);
2735
}
28-
2936
}
3037

3138
@Override
@@ -34,13 +41,21 @@ public <T> T getData() {
3441
return (T) data;
3542
}
3643

37-
public void setData(Object result) {
38-
this.data = result;
39-
}
40-
4144
@Override
4245
public List<GraphQLError> getErrors() {
4346
return new ArrayList<>(errors);
4447
}
4548

49+
@Override
50+
public Map<String, Object> toSpecification() {
51+
Map<String, Object> result = new LinkedHashMap<>();
52+
if (dataPresent) {
53+
result.put("data", data);
54+
}
55+
if (errors != null && !errors.isEmpty()) {
56+
result.put("errors", errors);
57+
}
58+
return result;
59+
}
60+
4661
}

‎src/test/groovy/example/http/HttpMain.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private void handleStarWars(HttpServletRequest httpRequest, HttpServletResponse
103103
private void returnAsJson(HttpServletResponse response, ExecutionResult executionResult) throws IOException {
104104
response.setContentType("application/json");
105105
response.setStatus(HttpServletResponse.SC_OK);
106-
JsonKit.toJson(response, executionResult);
106+
JsonKit.toJson(response, executionResult.toSpecification());
107107
}
108108

109109
private GraphQLSchema buildStarWarsSchema() {

‎src/test/groovy/example/http/JsonKit.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.google.gson.Gson;
44
import com.google.gson.GsonBuilder;
55
import com.google.gson.reflect.TypeToken;
6-
import graphql.ExecutionResult;
76

87
import javax.servlet.http.HttpServletResponse;
98
import java.io.IOException;
@@ -21,8 +20,8 @@ public class JsonKit {
2120
.serializeNulls()
2221
.create();
2322

24-
public static void toJson(HttpServletResponse response, ExecutionResult executionResult) throws IOException {
25-
GSON.toJson(executionResult, response.getWriter());
23+
public static void toJson(HttpServletResponse response, Object result) throws IOException {
24+
GSON.toJson(result, response.getWriter());
2625
}
2726

2827
public static Map<String, Object> toMap(String jsonStr) {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package graphql
2+
3+
import graphql.language.SourceLocation
4+
import spock.lang.Specification
5+
6+
class ExecutionResultTest extends Specification {
7+
8+
def KNOWN_ERRORS = [new InvalidSyntaxError(new SourceLocation(666,664))]
9+
10+
11+
def "data with no errors"() {
12+
given:
13+
def er = new ExecutionResultImpl("hello world", null)
14+
when:
15+
def actual = er.getData()
16+
def errors = er.getErrors()
17+
def specMap = er.toSpecification()
18+
then:
19+
actual == "hello world"
20+
21+
errors.size() == 0
22+
23+
specMap.size() == 1
24+
specMap["data"] == "hello world"
25+
}
26+
27+
def "errors and data"() {
28+
given:
29+
def er = new ExecutionResultImpl("hello world", KNOWN_ERRORS)
30+
when:
31+
def actual = er.getData()
32+
def errors = er.getErrors()
33+
def specMap = er.toSpecification()
34+
then:
35+
actual == "hello world"
36+
37+
errors.size() == 1
38+
errors == KNOWN_ERRORS
39+
40+
specMap.size() == 2
41+
specMap["data"] == "hello world"
42+
specMap["errors"] == KNOWN_ERRORS
43+
}
44+
45+
def "errors and no data"() {
46+
given:
47+
def er = new ExecutionResultImpl(KNOWN_ERRORS)
48+
when:
49+
def actual = er.getData()
50+
def errors = er.getErrors()
51+
def specMap = er.toSpecification()
52+
then:
53+
actual == null
54+
55+
errors.size() == 1
56+
errors == KNOWN_ERRORS
57+
58+
specMap.size() == 1
59+
specMap["errors"] == KNOWN_ERRORS
60+
}
61+
62+
}

0 commit comments

Comments
 (0)