Skip to content

Commit 65ec46a

Browse files
authored
fix: empty array instead of object handling (#185)
1 parent 90ee4e6 commit 65ec46a

File tree

5 files changed

+172
-23
lines changed

5 files changed

+172
-23
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.crowdin.client.core.http.impl.json;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.core.JsonToken;
6+
import com.fasterxml.jackson.databind.*;
7+
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
8+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
9+
10+
import java.io.IOException;
11+
import java.util.Collection;
12+
13+
public class EmptyArrayToNullDeserializer extends StdDeserializer<Object> implements ContextualDeserializer {
14+
private JavaType type;
15+
16+
public EmptyArrayToNullDeserializer() {
17+
super(Object.class);
18+
}
19+
20+
public EmptyArrayToNullDeserializer(JavaType type) {
21+
super(type.getRawClass());
22+
this.type = type;
23+
}
24+
25+
@Override
26+
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
27+
if (p.getCurrentToken() == JsonToken.VALUE_NULL) {
28+
return null;
29+
}
30+
31+
Class<?> clazz = this.type != null ? this.type.getRawClass() : Object.class;
32+
33+
if (p.getCurrentToken() == JsonToken.START_ARRAY) {
34+
if (!isCollectionType(clazz)) {
35+
p.nextToken();
36+
return null;
37+
} else {
38+
return ctxt.readValue(p, clazz);
39+
}
40+
}
41+
42+
return ctxt.readValue(p, clazz);
43+
}
44+
45+
private static boolean isCollectionType(Class<?> type) {
46+
return type.isArray() && Collection.class.isAssignableFrom(type);
47+
}
48+
49+
@Override
50+
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
51+
return new EmptyArrayToNullDeserializer(property.getType());
52+
}
53+
}

src/main/java/com/crowdin/client/projectsgroups/model/ProjectSettings.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.crowdin.client.projectsgroups.model;
22

3+
import com.crowdin.client.core.http.impl.json.EmptyArrayToNullDeserializer;
34
import com.crowdin.client.languages.model.Language;
5+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
46
import lombok.Data;
57
import lombok.EqualsAndHashCode;
68
import lombok.ToString;
@@ -39,6 +41,7 @@ public class ProjectSettings extends Project {
3941
private Map<String, Map<String, String>> languageMapping;
4042
private Boolean delayedWorkflowStart;
4143
private NotificationSettings notificationSettings;
42-
private TmPenalties[] tmPenalties;
44+
@JsonDeserialize(using = EmptyArrayToNullDeserializer.class)
45+
private TmPenalties tmPenalties;
4346

4447
}

src/test/java/com/crowdin/client/projectsgroups/ProjectsGroupsApiTest.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@
2727
import java.util.Map;
2828

2929
import static java.util.Collections.singletonList;
30-
import static org.junit.jupiter.api.Assertions.assertEquals;
31-
import static org.junit.jupiter.api.Assertions.assertFalse;
32-
import static org.junit.jupiter.api.Assertions.assertNotNull;
33-
import static org.junit.jupiter.api.Assertions.assertTrue;
30+
import static org.junit.jupiter.api.Assertions.*;
3431

3532
public class ProjectsGroupsApiTest extends TestClient {
3633

@@ -39,6 +36,7 @@ public class ProjectsGroupsApiTest extends TestClient {
3936
private final String groupName = "KB materials";
4037
private final Long projectId = 8L;
4138
private final Long projectSettingsId = 9L;
39+
private final Long projectSettingsId2 = 10L;
4240
private final String projectName = "Knowledge Base";
4341
private final String sourceLanguageId = "en";
4442
private final String targetLanguageId = "uk";
@@ -56,6 +54,7 @@ public List<RequestMock> getMocks() {
5654
RequestMock.build(this.url + "/projects", HttpPost.METHOD_NAME, "api/projectsgroups/addProjectRequest.json", "api/projectsgroups/project.json"),
5755
RequestMock.build(this.url + "/projects/" + projectId, HttpGet.METHOD_NAME, "api/projectsgroups/project.json"),
5856
RequestMock.build(this.url + "/projects/" + projectSettingsId, HttpGet.METHOD_NAME, "api/projectsgroups/projectSettings.json"),
57+
RequestMock.build(this.url + "/projects/" + projectSettingsId2, HttpGet.METHOD_NAME, "api/projectsgroups/projectSettings_tmPenaltiesArray.json"),
5958
RequestMock.build(this.url + "/projects/" + projectId, HttpDelete.METHOD_NAME),
6059
RequestMock.build(this.url + "/projects/" + projectId, HttpPatch.METHOD_NAME, "api/projectsgroups/editProject.json", "api/projectsgroups/project.json")
6160
);
@@ -174,7 +173,7 @@ public void getProjectSettingsTest() {
174173
assertFalse(qaChecksIgnorableCategories.getDuplicate());
175174
assertFalse(qaChecksIgnorableCategories.getFtl());
176175

177-
TmPenalties tmPenalties = projectSettings.getTmPenalties()[0];
176+
TmPenalties tmPenalties = projectSettings.getTmPenalties();
178177
assertNotNull(tmPenalties);
179178
assertEquals(1, tmPenalties.getAutoSubstitution());
180179
assertEquals(1, tmPenalties.getMultipleTranslations());
@@ -195,6 +194,14 @@ public void getProjectSettingsTest() {
195194
assertEquals(1, lastModified.getPenalty());
196195
}
197196

197+
@Test
198+
public void getProjectSettingsTest_tmPenaltiesEmptyArray() {
199+
ResponseObject<? extends Project> response = this.getProjectsGroupsApi().getProject(projectSettingsId2);
200+
201+
ProjectSettings settings = (ProjectSettings) response.getData();
202+
assertNull(settings.getTmPenalties());
203+
}
204+
198205
@Test
199206
public void deleteProjectTest() {
200207
this.getProjectsGroupsApi().deleteProject(projectId);

src/test/resources/api/projectsgroups/projectSettings.json

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,23 +83,21 @@
8383
"managerNewStrings": false,
8484
"managerLanguageCompleted": false
8585
},
86-
"tmPenalties": [
87-
{
88-
"autoSubstitution": 1,
89-
"tmPriority": {
90-
"priority": 2,
91-
"penalty": 1
92-
},
93-
"multipleTranslations": 1,
94-
"timeSinceLastUsage": {
95-
"months": 2,
96-
"penalty": 1
97-
},
98-
"timeSinceLastModified": {
99-
"months": 2,
100-
"penalty": 1
101-
}
86+
"tmPenalties": {
87+
"autoSubstitution": 1,
88+
"tmPriority": {
89+
"priority": 2,
90+
"penalty": 1
91+
},
92+
"multipleTranslations": 1,
93+
"timeSinceLastUsage": {
94+
"months": 2,
95+
"penalty": 1
96+
},
97+
"timeSinceLastModified": {
98+
"months": 2,
99+
"penalty": 1
102100
}
103-
]
101+
}
104102
}
105103
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{
2+
"data": {
3+
"id": 9,
4+
"groupId": 4,
5+
"userId": 6,
6+
"sourceLanguageId": "es",
7+
"targetLanguageIds": [
8+
"uk"
9+
],
10+
"name": "Knowledge Base",
11+
"identifier": "1f198a4e907688bc65834a6d5a6000c3",
12+
"description": "Vault of all terms and their explanation",
13+
"logo": "data:image/png;",
14+
"background": "data:image/png;",
15+
"isExternal": false,
16+
"externalType": "proofread",
17+
"workflowId": 3,
18+
"hasCrowdsourcing": false,
19+
"createdAt": "2019-09-20T11:34:40+00:00",
20+
"updatedAt": "2019-09-20T11:34:40+00:00",
21+
"translateDuplicates": 1,
22+
"glossaryAccess": false,
23+
"isMtAllowed": true,
24+
"hiddenStringsProofreadersAccess": true,
25+
"autoSubstitution": true,
26+
"exportTranslatedOnly": false,
27+
"skipUntranslatedFiles": false,
28+
"exportApprovedOnly": false,
29+
"autoTranslateDialects": true,
30+
"publicDownloads": true,
31+
"useGlobalTm": false,
32+
"inContext": true,
33+
"inContextPseudoLanguageId": "uk",
34+
"isSuspended": false,
35+
"qaCheckIsActive": true,
36+
"qaCheckCategories": {
37+
"empty": true,
38+
"size": true,
39+
"tags": true,
40+
"spaces": true,
41+
"variables": true,
42+
"punctuation": true,
43+
"symbolRegister": true,
44+
"specialSymbols": true,
45+
"wrongTranslation": true,
46+
"spellcheck": true,
47+
"icu": true
48+
},
49+
"qaChecksIgnorableCategories": {
50+
"empty": false,
51+
"size": true,
52+
"tags": true,
53+
"spaces": true,
54+
"variables": true,
55+
"punctuation": true,
56+
"symbolRegister": true,
57+
"specialSymbols": true,
58+
"wrongTranslation": true,
59+
"spellcheck": true,
60+
"icu": false,
61+
"terms": true,
62+
"duplicate": false,
63+
"ftl": false,
64+
"android": true
65+
},
66+
"customQaCheckIds": [
67+
1
68+
],
69+
"languageMapping": {
70+
"uk": {
71+
"name": "Ukranian",
72+
"two_letters_code": "ua",
73+
"three_letters_code": "ukr",
74+
"locale": "uk-UA",
75+
"locale_with_underscore": "uk_UA",
76+
"android_code": "uk-rUA",
77+
"osx_code": "ua.lproj",
78+
"osx_locale": "ua"
79+
}
80+
},
81+
"notificationSettings": {
82+
"translatorNewStrings": true,
83+
"managerNewStrings": false,
84+
"managerLanguageCompleted": false
85+
},
86+
"tmPenalties": []
87+
}
88+
}

0 commit comments

Comments
 (0)