在 Android 中使用 GSON Retrofit 从动态嵌套 json 中排除空值
Exclude null values from dynamic nested json using GSON Retrofit in Android
我正在 Android 中使用 gson 和 Retrofit 解析动态嵌套 json。我想在将其添加到列表之前排除 null/empty 个值。
我尝试了以下方法,但 none 似乎有效:
// retMap.values().removeIf(Objects::isNull);
// Collection<POJOContent> values = retMap.values();
// while (values.remove(null)) {}
//list.removeAll(Arrays.asList(""));
CustomDeserialiser.java
public class CustomDeserializer implements JsonDeserializer<MyContentWrapper> {
private final String abc_key = "abc";
@Override
public MyContentWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
MyContentWrapper abc = new MyContentWrapper();
JsonObject object = json.getAsJsonObject().getAsJsonObject(abc_key);
List<POJOContent> list = new ArrayList<POJOContent>();
System.out.println("New Data: "+object);
for (Map.Entry<String, JsonElement> set : object.entrySet()) {
System.out.println("LIST " + set);
JsonObject nextObject = object.getAsJsonObject().getAsJsonObject(set.getKey());
Map<String, POJOContent> retMap = new Gson().fromJson(nextObject, new TypeToken<LinkedHashMap<String, POJOContent>>() {
}.getType());
// retMap.values().removeIf(Objects::isNull);
// Collection<POJOContent> values = retMap.values();
// while (values.remove(null)) {}
list.addAll(retMap.values());
//list.removeAll(Arrays.asList(""));
}
abc.abc = list;
return abc;
}
POJOContent.java
public class POJOContent {
@SerializedName("ab")
public String content;
@SerializedName("id")
public String id;
@SerializedName("key")
public String key;
@Override
public String toString() {
return content;
}
//getters and setters
}
MyContentWrapper.java
public class MyContentWrapper {
public List<POJOContent> abc;
}
JSON:
{
"abc": {
"1": {
"1": {
"ab": "some content",
"id": "240",
"key": "value"
},
"2": {
"ab": "some content",
"id": "240",
"key": "value"
},
"3": {
"ab": "some content",
"id": "240",
"key": "value"
}
},
"2": {
"1": {
"ab": "some content",
"id": "241",
"key": "value"
},
"2": {
"ab": "some content",
"id": "241",
"key": "value"
},
"3": {
"ab": "some content",
"id": "241",
"key": "value"
}
},
"3": {
"1": {
"ab": "",
"id": "252",
"key": "value"
},
"2": {
"ab": "some content",
"id": "252",
"key": "value"
},
"3": {
"ab": "",
"id": "252",
"key": "value"
}
}
}
}
基本上,我想跳过“ab”值为空的对象,而不是将它们添加到列表中(如果“ab”值为空,则其他键无关紧要)。澄清一下,如果父对象有任何带有“ab”键空值的子对象,则应排除该子对象。如果父对象的所有子对象的“ab”键为空值,则应排除父对象。
我错过了什么吗?非常感谢您的帮助。
编辑:: 预期 JSON:
{
"abc": {
"1": {
"1": {
"ab": "some content",
"id": "240",
"key": "value"
},
"2": {
"ab": "some content",
"id": "240",
"key": "value"
},
"3": {
"ab": "some content",
"id": "240",
"key": "value"
}
},
"2": {
"1": {
"ab": "some content",
"id": "241",
"key": "value"
},
"2": {
"ab": "some content",
"id": "241",
"key": "value"
},
"3": {
"ab": "some content",
"id": "241",
"key": "value"
}
},
"3": {
"2": {
"ab": "some content",
"id": "252",
"key": "value"
}
}
}
}
更新 2:
这是我将列表更改为地图后得到的响应:
Callback<MyContentWrapper> myCallback = new Callback<MyContentWrapper>() {
@Override
public void onResponse(Call<MyContentWrapper> call, Response<MyContentWrapper> response) {
if (response.isSuccessful()) {
Log.d("Callback", " Message: " + response.raw());
Log.d("Callback", " Message: " + response.body().abc.values());
still showing empty brackets here --->
//Log.d = Message: [{1=1. some content, 1=2. some content, 1=3. some content}, {}]
} else {
Log.d("Callback", "Code: " + response.code() + " Message: " + response.message());
}
}
@Override
public void onFailure(Call<MyContentWrapper> call, Throwable t) {
t.printStackTrace();
}
};
仅供参考,这是对上述回调的 JSON 响应:
{
"abc": {
"1": {
"1": {
"ab": "some content",
"id": "240",
"key": "value"
},
"2": {
"ab": "some content",
"id": "240",
"key": "value"
},
"3": {
"ab": "some content",
"id": "240",
"key": "value"
}
},
"2": {
"1": {
"ab": "",
"id": "241",
"key": "value"
},
"2": {
"ab": "",
"id": "241",
"key": "value"
},
"3": {
"ab": "",
"id": "241",
"key": "value"
}
}
}
}
首先你的MyContentWrapper
是错误的。根据您的 JSON,它不是 List
。它应该是地图的地图,类似于:
public class MyContentWrapper {
public Map<Integer, Map<Integer, POJOContent>> abc;
}
现在,您可以为这种结构编写一些复杂的反序列化器,但还有另一种方法可以做到这一点。也就是说,如果你声明 helper Map
像:
@SuppressWarnings("serial")
public class MyMap extends HashMap<Integer, POJOContent> {
@Override
public POJOContent put(Integer key, POJOContent value) {
if(null==value.getContent() || value.getContent().isBlank()) {
return null;
}
// Added only if content = "ab" is not blank.
return super.put(key, value);
}
}
然后调谐 MyContentWrapper
:
public class MyContentWrapper {
public Map<Integer, MyMap> abc;
}
那就只有:
MyContentWrapper mcw = new Gson().fromJson(JSON, MyContentWrapper.class);
我正在 Android 中使用 gson 和 Retrofit 解析动态嵌套 json。我想在将其添加到列表之前排除 null/empty 个值。
我尝试了以下方法,但 none 似乎有效:
// retMap.values().removeIf(Objects::isNull);
// Collection<POJOContent> values = retMap.values();
// while (values.remove(null)) {}
//list.removeAll(Arrays.asList(""));
CustomDeserialiser.java
public class CustomDeserializer implements JsonDeserializer<MyContentWrapper> {
private final String abc_key = "abc";
@Override
public MyContentWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
MyContentWrapper abc = new MyContentWrapper();
JsonObject object = json.getAsJsonObject().getAsJsonObject(abc_key);
List<POJOContent> list = new ArrayList<POJOContent>();
System.out.println("New Data: "+object);
for (Map.Entry<String, JsonElement> set : object.entrySet()) {
System.out.println("LIST " + set);
JsonObject nextObject = object.getAsJsonObject().getAsJsonObject(set.getKey());
Map<String, POJOContent> retMap = new Gson().fromJson(nextObject, new TypeToken<LinkedHashMap<String, POJOContent>>() {
}.getType());
// retMap.values().removeIf(Objects::isNull);
// Collection<POJOContent> values = retMap.values();
// while (values.remove(null)) {}
list.addAll(retMap.values());
//list.removeAll(Arrays.asList(""));
}
abc.abc = list;
return abc;
}
POJOContent.java
public class POJOContent {
@SerializedName("ab")
public String content;
@SerializedName("id")
public String id;
@SerializedName("key")
public String key;
@Override
public String toString() {
return content;
}
//getters and setters
}
MyContentWrapper.java
public class MyContentWrapper {
public List<POJOContent> abc;
}
JSON:
{
"abc": {
"1": {
"1": {
"ab": "some content",
"id": "240",
"key": "value"
},
"2": {
"ab": "some content",
"id": "240",
"key": "value"
},
"3": {
"ab": "some content",
"id": "240",
"key": "value"
}
},
"2": {
"1": {
"ab": "some content",
"id": "241",
"key": "value"
},
"2": {
"ab": "some content",
"id": "241",
"key": "value"
},
"3": {
"ab": "some content",
"id": "241",
"key": "value"
}
},
"3": {
"1": {
"ab": "",
"id": "252",
"key": "value"
},
"2": {
"ab": "some content",
"id": "252",
"key": "value"
},
"3": {
"ab": "",
"id": "252",
"key": "value"
}
}
}
}
基本上,我想跳过“ab”值为空的对象,而不是将它们添加到列表中(如果“ab”值为空,则其他键无关紧要)。澄清一下,如果父对象有任何带有“ab”键空值的子对象,则应排除该子对象。如果父对象的所有子对象的“ab”键为空值,则应排除父对象。
我错过了什么吗?非常感谢您的帮助。
编辑:: 预期 JSON:
{
"abc": {
"1": {
"1": {
"ab": "some content",
"id": "240",
"key": "value"
},
"2": {
"ab": "some content",
"id": "240",
"key": "value"
},
"3": {
"ab": "some content",
"id": "240",
"key": "value"
}
},
"2": {
"1": {
"ab": "some content",
"id": "241",
"key": "value"
},
"2": {
"ab": "some content",
"id": "241",
"key": "value"
},
"3": {
"ab": "some content",
"id": "241",
"key": "value"
}
},
"3": {
"2": {
"ab": "some content",
"id": "252",
"key": "value"
}
}
}
}
更新 2:
这是我将列表更改为地图后得到的响应:
Callback<MyContentWrapper> myCallback = new Callback<MyContentWrapper>() {
@Override
public void onResponse(Call<MyContentWrapper> call, Response<MyContentWrapper> response) {
if (response.isSuccessful()) {
Log.d("Callback", " Message: " + response.raw());
Log.d("Callback", " Message: " + response.body().abc.values());
still showing empty brackets here --->
//Log.d = Message: [{1=1. some content, 1=2. some content, 1=3. some content}, {}]
} else {
Log.d("Callback", "Code: " + response.code() + " Message: " + response.message());
}
}
@Override
public void onFailure(Call<MyContentWrapper> call, Throwable t) {
t.printStackTrace();
}
};
仅供参考,这是对上述回调的 JSON 响应:
{
"abc": {
"1": {
"1": {
"ab": "some content",
"id": "240",
"key": "value"
},
"2": {
"ab": "some content",
"id": "240",
"key": "value"
},
"3": {
"ab": "some content",
"id": "240",
"key": "value"
}
},
"2": {
"1": {
"ab": "",
"id": "241",
"key": "value"
},
"2": {
"ab": "",
"id": "241",
"key": "value"
},
"3": {
"ab": "",
"id": "241",
"key": "value"
}
}
}
}
首先你的MyContentWrapper
是错误的。根据您的 JSON,它不是 List
。它应该是地图的地图,类似于:
public class MyContentWrapper {
public Map<Integer, Map<Integer, POJOContent>> abc;
}
现在,您可以为这种结构编写一些复杂的反序列化器,但还有另一种方法可以做到这一点。也就是说,如果你声明 helper Map
像:
@SuppressWarnings("serial")
public class MyMap extends HashMap<Integer, POJOContent> {
@Override
public POJOContent put(Integer key, POJOContent value) {
if(null==value.getContent() || value.getContent().isBlank()) {
return null;
}
// Added only if content = "ab" is not blank.
return super.put(key, value);
}
}
然后调谐 MyContentWrapper
:
public class MyContentWrapper {
public Map<Integer, MyMap> abc;
}
那就只有:
MyContentWrapper mcw = new Gson().fromJson(JSON, MyContentWrapper.class);