Remove empty collections from a JSON with Gson

后端 未结 3 1456
滥情空心
滥情空心 2020-11-30 11:51

I want to remove attributes that have empty collections or null values using gson.

Aiperiodo periodo = periodoService();
//periodo comes fro         


        
3条回答
  •  甜味超标
    2020-11-30 12:51

    I tried a solution of @Braj in Kotlin. The idea is to convert JSON to Map, remove nulls and empty arrays, then convert Map back to JSON string.

    But it has several disadvantages.

    1. It can only work with simple POJOs without nestings (no inner classes, lists of classes).
    2. It converts numbers to doubles (because Object is not recognized as int).
    3. It loses time to convert from String to String.

    Alternatively you can try to use Moshi instead of Gson, see Broken server response handling with Moshi.

    After couple of days I overcame a 1st problem for complex JSONs.

    import android.support.annotation.NonNull;
    
    import com.google.gson.Gson;
    import com.google.gson.internal.LinkedTreeMap;
    import com.google.gson.reflect.TypeToken;
    
    import java.lang.reflect.Type;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.Map;
    
    
    public class GsonConverter {
    
        private Type type;
        private Gson gson;
    
    
        public GsonConverter() {
            type = new TypeToken>() {
            }.getType();
            gson = new Gson();
        }
    
        /**
         * Remove empty arrays from JSON.
         */
        public String cleanJson(String jsonString) {
            Map data = gson.fromJson(jsonString, type);
            if (data == null)
                return "";
    
            Iterator> it = data.entrySet().iterator();
            traverse(it);
    
            return gson.toJson(data);
        }
    
        private void traverse(@NonNull Iterator> iterator) {
            while (iterator.hasNext()) {
                Map.Entry entry = iterator.next();
                Object value = entry.getValue();
                if (value == null) {
                    iterator.remove();
                    continue;
                }
    
                Class aClass = value.getClass();
                if (aClass.equals(ArrayList.class)) {
                    if (((ArrayList) value).isEmpty()) {
                        iterator.remove();
                        continue;
                    }
                }
    
                // Recoursively pass all tags for the next level.
                if (aClass.equals(ArrayList.class)) {
                    Object firstItem = ((ArrayList) value).get(0);
                    Class firstItemClass = firstItem.getClass();
    
                    // Check that we have an array of non-strings (maps).
                    if (firstItemClass.equals(Map.class)) {
                        // Array of keys and values.
                        @SuppressWarnings("unchecked")
                        ArrayList> items = (ArrayList>) value;
                        for (Map item : items) {
                            traverse(item.entrySet().iterator());
                        }
                    } else if (firstItemClass.equals(LinkedTreeMap.class)) {
                        // Array of complex objects.
                        @SuppressWarnings("unchecked")
                        ArrayList> items = (ArrayList>) value;
                        for (LinkedTreeMap item : items) {
                            traverse(item.entrySet().iterator());
                        }
                    }
                } else if (aClass.equals(LinkedTreeMap.class)) {
                    @SuppressWarnings("unchecked")
                    LinkedTreeMap value2 = (LinkedTreeMap) value;
                    traverse(value2.entrySet().iterator());
                }
            }
        }
    }
    

    Usage:

    YourJsonObject yourJsonObject = new Gson().fromJson(new GsonConverter().cleanJson(json), YourJsonObject.class);
    

    For those who want to use @Braj solution, here is a code in Kotlin.

    import com.google.gson.Gson
    import com.google.gson.GsonBuilder
    import com.google.gson.reflect.TypeToken
    import java.lang.reflect.Type
    
    
    class GsonConverter {
    
        private val type: Type = object : TypeToken>() {}.type
        private val gson = Gson()
        private val gsonBuilder: GsonBuilder = GsonBuilder()//.setLongSerializationPolicy(LongSerializationPolicy.STRING)
    
    
        fun convert(jsonString: String): String {
            val data: Map = gson.fromJson(jsonString, type)
    
            val obj = data.filter { it.value != null && ((it.value as? ArrayList<*>)?.size != 0) }
    
            val json = gsonBuilder/*.setPrettyPrinting()*/.create().toJson(obj)
            println(json)
    
            return json
        }
    }
    

提交回复
热议问题