简体   繁体   中英

Realm Serializing Data from Map

I am working with Realm for Android, I had to work with storage of maps. However, Realm does not support maps and so I made a workaround for this as suggested here

But when I am serializing the data I am storing to a JSON, the output is way off of what is expected.

The expected JSON:

{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4"
}

And what I am getting is:

[{
"key": "key1",
"value": "value1"
},
{
"key": "key2",
"value": "value2"
},
{
"key": "key3",
"value": "value3"
}]

My Code:

public class ActivityDetails extends RealmObject {
    public RealmList<KeyValueStore> map;
    public String bid;
    public String s;
}

public class KeyValueStore extends RealmObject {
    private String key;
    private String value;

    public void setKey(String key) {
        this.key = key;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

Is there a way to serialize the map like data as expected?

Edit: The following is the complete object that is my data (as expected)

{
  "s": "someValue",
  "bid": "someValue",
  "map": [
    {
      "key": "key1",
      "value": "value1"
    },
    {
      "key": "key2",
      "value": "value2"
    },
    {
      "key": "key3",
      "value": "value3"
    }
  ]
}

Might be too late, but since I have tried to solve same problem, I came up with solution of writing custom JSON serializer/deserializer:

public class KeyValueSerializer implements JsonSerializer<RealmList<KeyValue>>,
                                           JsonDeserializer<RealmList<KeyValue>> {
    @Override
    public JsonElement serialize(RealmList<KeyValue> src,
                                 Type typeOfSrc,
                                 JsonSerializationContext context) {

        JsonObject keyValueJson = new JsonObject();

        for(KeyValue keyValue : src) {
            keyValueJson.addProperty(keyValue.getKey(), keyValue.getValue());
        }

        return keyValueJson;
    }

    @Override
    public RealmList<KeyValue> deserialize(JsonElement json,
                                           Type typeOfT,
                                           JsonDeserializationContext context) throws JsonParseException {

        Type type = new TypeToken<Map<String, String>>() {}.getType();
        Map<String, String> data = new Gson().fromJson(json, type);

        RealmList<KeyValue> keyValues = new RealmList<>();

        for (Map.Entry<String, String> entry : data.entrySet()) {
            KeyValue keyValue = new KeyValue();
            keyValue.setKey(entry.getKey());
            keyValue.setValue(entry.getValue());

            keyValues.add(keyValue);
        }

        return keyValues;
    }
}

Where the KeyValue class follows the same map representation as proposed here :

public class KeyValue extends RealmObject {
    private String key;
    private String value;

    public KeyValue() {

    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

RealmList is a generic type, so it can't be addressed with a .class . Use TypeToken to get a Type when registering a TypeAdapter and calling fromJson method:

Type keyValueRealmListType = new TypeToken<RealmList<KeyValue>>() {}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(keyValueRealmListType, 
                                             new KeyValueSerializer())
           .create();

RealmList<KeyValue> keyValues = gson.fromJson(keyValuesJson,
                                              keyValueRealmListType);

As far as I have tested, a custom serializer/deserializer like this should read and write JSON in preferred format like it is in the question. I find it a bit hacky, but it does the job.

If

{
    "key": "key1",
    "value": "value1"
}

This represents your entire data, then this should be your entire RealmModel.

public class MyObject extends RealmObject {
    @PrimaryKey
    private String key;

    private String value;

    // getters setters
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM