Skip to content

Commit 21ce846

Browse files
authored
Merge pull request #263 from contentstack/feat/DX-4424-assetField-support
enhancement: asset field support
2 parents f413e39 + 4c6be0b commit 21ce846

File tree

13 files changed

+527
-4
lines changed

13 files changed

+527
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,4 @@ src/main/resources/
274274
/.vscode/
275275
/docs/
276276
INTEGRATION-TESTS-GUIDE.md
277+
src/main/java/com/demo/*

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## v2.5.0
4+
5+
### Feb 12, 2026
6+
- Enhancement: assetFields method added
7+
38
## v2.4.0
49

510
### Feb 02, 2026

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>com.contentstack.sdk</groupId>
77
<artifactId>java</artifactId>
8-
<version>2.4.0</version>
8+
<version>2.5.0</version>
99
<packaging>jar</packaging>
1010
<name>contentstack-java</name>
1111
<description>Java SDK for Contentstack Content Delivery API</description>

src/main/java/com/contentstack/sdk/Asset.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.contentstack.sdk;
22

33
import org.jetbrains.annotations.NotNull;
4+
import org.json.JSONArray;
45
import org.json.JSONObject;
56
import retrofit2.Retrofit;
67
import lombok.Getter;
@@ -544,6 +545,19 @@ public Asset includeMetadata() {
544545
return this;
545546
}
546547

548+
public Asset assetFields(String... fields) {
549+
if (fields != null && fields.length > 0) {
550+
JSONArray array = new JSONArray();
551+
for (String field : fields) {
552+
array.put(field);
553+
}
554+
if (!array.isEmpty()) {
555+
urlQueries.put("asset_fields[]", array);
556+
}
557+
}
558+
return this;
559+
}
560+
547561
/**
548562
* Fetch.
549563
*

src/main/java/com/contentstack/sdk/AssetLibrary.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.jetbrains.annotations.NotNull;
44
import org.json.JSONObject;
5+
import org.json.JSONArray;
56

67
import java.util.*;
78
import java.util.logging.Logger;
@@ -33,7 +34,8 @@ protected void setStackInstance(@NotNull Stack stack) {
3334

3435
//Sanitization of keys
3536
private boolean isValidKey(String key) {
36-
return key.matches("^[a-zA-Z0-9_.]+$");
37+
// Fixed regex: allow alphanumeric, underscore, dot, and square brackets at the end, escaped properly
38+
return key.matches("^[a-zA-Z0-9_.]+(\\[\\])?$");
3739
}
3840

3941
//Sanitization of values
@@ -265,6 +267,19 @@ public AssetLibrary limit (@NotNull int number) {
265267
return this;
266268
}
267269

270+
public AssetLibrary assetFields(String... fields) {
271+
if (fields != null && fields.length > 0) {
272+
JSONArray array = new JSONArray();
273+
for (String field : fields) {
274+
array.put(field);
275+
}
276+
if (!array.isEmpty()) {
277+
urlQueries.put("asset_fields[]", array);
278+
}
279+
}
280+
return this;
281+
}
282+
268283
/**
269284
* Fetch all.
270285
*

src/main/java/com/contentstack/sdk/CSHttpConnection.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ public String setFormParamsGET(HashMap<String, Object> params) {
102102
if (params != null && params.size() > 0) {
103103
String urlParams = null;
104104
urlParams = info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.QUERY.name())
105-
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ENTRY.name()) ? getParams(params) : null;
105+
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ENTRY.name())
106+
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ASSET.name())
107+
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ASSETLIBRARY.name()) ? getParams(params) : null;
106108
if (urlParams == null) {
107109
for (Map.Entry<String, Object> e : params.entrySet()) {
108110
if (urlParams == null) {
@@ -124,7 +126,7 @@ private String getParams(HashMap<String, Object> params) {
124126
Object value = e.getValue();
125127
try {
126128
if (key.equalsIgnoreCase("include[]") || key.equalsIgnoreCase("only[BASE][]")
127-
|| key.equalsIgnoreCase("except[BASE][]")) {
129+
|| key.equalsIgnoreCase("except[BASE][]") || key.equalsIgnoreCase("asset_fields[]")) {
128130
urlParams = convertUrlParam(urlParams, value, key);
129131
} else if (key.equalsIgnoreCase("only")) {
130132
JSONObject onlyJSON = (JSONObject) value;

src/main/java/com/contentstack/sdk/Entry.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,19 @@ public Entry exceptWithReferenceUid(@NotNull List<String> fieldUid, @NotNull Str
904904
return this;
905905
}
906906

907+
908+
public Entry assetFields(String... fields) {
909+
if (fields != null && fields.length > 0) {
910+
JSONArray array = new JSONArray();
911+
for (String field : fields) {
912+
array.put(field);
913+
}
914+
if (!array.isEmpty()) {
915+
params.put("asset_fields[]", array);
916+
}
917+
}
918+
return this;
919+
}
907920
/**
908921
* Fetches the latest version of the entries from Contentstack.com content stack
909922
*

src/main/java/com/contentstack/sdk/Query.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,19 @@ public Query search(@NotNull String value) {
11461146
return this;
11471147
}
11481148

1149+
public Query assetFields(String... fields) {
1150+
if (fields != null && fields.length > 0) {
1151+
JSONArray array = new JSONArray();
1152+
for (String field : fields) {
1153+
array.put(field);
1154+
}
1155+
if (!array.isEmpty()) {
1156+
urlQueries.put("asset_fields[]", array);
1157+
}
1158+
}
1159+
return this;
1160+
}
1161+
11491162
/**
11501163
* Execute a Query and Caches its result (Optional)
11511164
*

src/test/java/com/contentstack/sdk/TestAsset.java

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,133 @@ void testIncludeMetadata() {
182182
assertEquals(true, asset.urlQueries.get("include_metadata"));
183183
}
184184

185+
// ========== ASSET FIELDS TESTS (CDA asset_fields[] parameter) ==========
186+
187+
@Test
188+
void testAssetFieldsWithSupportedValues() {
189+
Asset result = asset.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups");
190+
assertSame(asset, result);
191+
assertTrue(asset.urlQueries.has("asset_fields[]"));
192+
Object val = asset.urlQueries.get("asset_fields[]");
193+
assertTrue(val instanceof JSONArray);
194+
JSONArray arr = (JSONArray) val;
195+
assertEquals(4, arr.length());
196+
assertEquals("user_defined_fields", arr.get(0));
197+
assertEquals("embedded", arr.get(1));
198+
assertEquals("ai_suggested", arr.get(2));
199+
assertEquals("visual_markups", arr.get(3));
200+
}
201+
202+
@Test
203+
void testAssetFieldsReturnsThis() {
204+
Asset result = asset.assetFields("user_defined_fields");
205+
assertSame(asset, result);
206+
}
207+
208+
@Test
209+
void testAssetFieldsWithNoArgsDoesNotSetParam() {
210+
asset.assetFields();
211+
assertFalse(asset.urlQueries.has("asset_fields[]"));
212+
}
213+
214+
@Test
215+
void testAssetFieldsWithNullDoesNotSetParam() {
216+
asset.assetFields((String[]) null);
217+
assertFalse(asset.urlQueries.has("asset_fields[]"));
218+
}
219+
220+
@Test
221+
void testAssetFieldsChainingWithOtherMethods() {
222+
Asset result = asset.assetFields("embedded", "visual_markups")
223+
.includeMetadata()
224+
.includeDimension();
225+
assertSame(asset, result);
226+
assertTrue(asset.urlQueries.has("asset_fields[]"));
227+
assertTrue(asset.urlQueries.has("include_metadata"));
228+
assertTrue(asset.urlQueries.has("include_dimension"));
229+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
230+
assertEquals(2, arr.length());
231+
assertEquals("embedded", arr.get(0));
232+
assertEquals("visual_markups", arr.get(1));
233+
}
234+
235+
/**
236+
* Usage: stack.asset(assetUid).assetFields(...).fetch()
237+
* Verifies the full chain sets asset_fields[] on the asset before fetch.
238+
*/
239+
@Test
240+
void testUsageSingleAssetFetchWithAssetFields() throws IllegalAccessException {
241+
Stack stack = Contentstack.stack("api_key", "delivery_token", "env");
242+
Asset asset = stack.asset("asset_uid_123")
243+
.assetFields("embedded", "visual_markups");
244+
assertTrue(asset.urlQueries.has("asset_fields[]"));
245+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
246+
assertEquals(2, arr.length());
247+
assertEquals("embedded", arr.get(0));
248+
assertEquals("visual_markups", arr.get(1));
249+
}
250+
251+
252+
@Test
253+
void testAssetFieldsSingleField() {
254+
asset.assetFields("embedded");
255+
assertTrue(asset.urlQueries.has("asset_fields[]"));
256+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
257+
assertEquals(1, arr.length());
258+
assertEquals("embedded", arr.get(0));
259+
}
260+
261+
@Test
262+
void testAssetFieldsEmptyVarargsArrayDoesNotSetParam() {
263+
asset.assetFields(new String[0]);
264+
assertFalse(asset.urlQueries.has("asset_fields[]"));
265+
}
266+
267+
@Test
268+
void testAssetFieldsDuplicateValuesAllowed() {
269+
asset.assetFields("embedded", "embedded");
270+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
271+
assertEquals(2, arr.length());
272+
assertEquals("embedded", arr.get(0));
273+
assertEquals("embedded", arr.get(1));
274+
}
275+
276+
@Test
277+
void testAssetFieldsSecondCallOverwrites() {
278+
asset.assetFields("user_defined_fields", "embedded");
279+
asset.assetFields("ai_suggested");
280+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
281+
assertEquals(1, arr.length());
282+
assertEquals("ai_suggested", arr.get(0));
283+
}
284+
285+
@Test
286+
void testAssetFieldsWithEmptyStringInArray() {
287+
asset.assetFields("valid", "", "embedded");
288+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
289+
assertEquals(3, arr.length());
290+
assertEquals("valid", arr.get(0));
291+
assertEquals("", arr.get(1));
292+
assertEquals("embedded", arr.get(2));
293+
}
294+
295+
@Test
296+
void testAssetFieldsWithNullInArray() {
297+
asset.assetFields("valid", null, "embedded");
298+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
299+
assertEquals(3, arr.length());
300+
assertEquals("valid", arr.get(0));
301+
assertEquals("embedded", arr.get(2));
302+
}
303+
304+
@Test
305+
void testAssetFieldsSingleEmptyStringSetsParam() {
306+
asset.assetFields("");
307+
assertTrue(asset.urlQueries.has("asset_fields[]"));
308+
assertEquals(1, asset.urlQueries.getJSONArray("asset_fields[]").length());
309+
assertEquals("", asset.urlQueries.getJSONArray("asset_fields[]").get(0));
310+
}
311+
185312
// ========== CHAINING TESTS ==========
186313

187314
@Test

0 commit comments

Comments
 (0)