Nano Java8
Nano Java8

Reputation: 51

How to serialize an Object to Map by Moshi

I want to serialize an Object to Map by Moshi.Here is my codes by Gson

    public static Map<String, String> toMap(Object obj, Gson gson) {
    if (gson == null) {
        gson = new Gson();
    }
    String json = gson.toJson(obj);
    Map<String, String> map = gson.fromJson(json, new TypeToken<Map<String, String>>() {
    }.getType());
    return map;
}

And how to write by Moshi ?

Upvotes: 4

Views: 20387

Answers (5)

Sasha Balyas
Sasha Balyas

Reputation: 440

In Kotlin:

val type = Types.newParameterizedType(
            MutableMap::class.java,
            String::class.java,
            String::class.java
        )
        val adapter: JsonAdapter<Map<String, String>> = moshi.adapter(type)
        val map: Map<String, String> = adapter.fromJson(responseJson)

Upvotes: 4

Kristy Welsh
Kristy Welsh

Reputation: 8362

class HashMapJsonAdapter<K, V>(
  private val keyAdapter: JsonAdapter<K>,
  private val valueAdapter: JsonAdapter<V>
) : JsonAdapter<HashMap<K, V>>() {

  @Throws(IOException::class)
  override fun toJson(writer: JsonWriter, map: HashMap<K, V>?) {
    writer.beginObject()
    for ((key, value) in map ?: emptyMap<K, V>()) {
      if (key == null) {
        throw JsonDataException("Map key is null at ${writer.path}")
      }
    keyAdapter.toJson(writer, key)
    valueAdapter.toJson(writer, value)
    }
    writer.endObject()
  }

  @Throws(IOException::class)
  override fun fromJson(reader: JsonReader): HashMap<K, V>? {
    val result = linkedMapOf<K, V>()
    reader.beginObject()
    while (reader.hasNext()) {
      val name = keyAdapter.fromJson(reader)
      val value = valueAdapter.fromJson(reader)
      val replaced = result.put(name!!, value!!)
      if (replaced != null) {
        throw JsonDataException("Map key '$name' has multiple values at path ${reader.path} : $replaced and value")
      }
    }
    reader.endObject()
    return result
  }

  override fun toString(): String = "JsonAdapter($keyAdapter=$valueAdapter)"

  companion object
}

Upvotes: 1

farhan patel
farhan patel

Reputation: 1610

@NanoJava8 solution crashes but can be made to work with a minor change using Map instead of HashMap

Type type = Types.newParameterizedType(Map.class, String.class, String.class);

JsonAdapter<Map<String,String>> adapter = moshi.adapter(type);

Map<String,String> map = adapter.fromJson(json);

As stated by Jesse in the answer Moshi support fields as Map but not HashMap.

Upvotes: 8

Eric Cochran
Eric Cochran

Reputation: 8574

Here's one way. Check out the toJsonValue doc here.

Moshi moshi = new Moshi.Builder().build();

JsonAdapter<Object> adapter = moshi.adapter(Object.class);

Object jsonStructure = adapter.toJsonValue(obj);
Map<String, Object> jsonObject = (Map<String, Object>) jsonStructure;

If you know the type of obj, it'd be better to look up the adapter of that type, rather than of Object. (The Object JsonAdadpter has to look up the runtime type on every toJson call.

Upvotes: 11

Nano Java8
Nano Java8

Reputation: 51

Type type = Types.newParameterizedType(HashMap.class, String.class, String.class);

JsonAdapter<Map<String,String>> adapter = moshi.adapter(type);

Map<String,String> map = adapter.fromJson(json);

Upvotes: 1

Related Questions