Edamame Edamame - 2 months ago 23
Scala Question

Scala: Json representation of an ArrayBuffer/ArrayList ... how to avoid printing out empty information in the collection?

I have an ArrayBuffer in my Scala class (somewhat like a ArrayList if using Java). The following is my code:

class MyClass {

val names: ArrayBuffer[Name] = new ArrayBuffer[Name]
var phone: String = null;

def toJsonString(): String = {
return (new GsonBuilder().serializeNulls().create()).toJson(this);
}

override def toString(): String = {
return toJsonString();
}
}


Then when I try to print my MyClass object:

var myObj = new MyClass

val name = new Name()
name.setFirstName("John")
name.setLastName("Smith")

myObj.names.append(name)

println(myObj.toString())





Then my output looks like:

{"names":{"initialSize":16,"array":[{"firstName":"John","middleName":null,"lastName":"Smith"},null,null,null,null,null,n
ull,null,null,null,null,null,null,null,null,null],"size0":1},"phone":null}


Is there a way I can make the output JSON like below? Perhaps using a different collection other than ArrayBuffer? Thanks!

{"names":[{"firstName":"John","middleName":null,"lastName":"Smith"}],"phone":null}

Answer

You have many good options (e.g. use another serialization library instead of Gson, use an immutable collection etc.), but here's a solution with minimal code changes:

Add a custom serializer for ArrayBuffer that converts it to an immutable Array, thus getting rid of the empty cells:

import com.google.gson._
import scala.reflect.ClassTag
import java.lang.reflect.Type

class ArrayBufferSerializer[T : ClassTag] extends JsonSerializer[ArrayBuffer[T]] {
    override def serialize(src: ArrayBuffer[T], typeOfSrc: Type, context: JsonSerializationContext): JsonElement = {
        context.serialize(src.toArray)
    }
}

Then register it in the GsonBuilder in MyClass.toJsonString:

def toJsonString(): String = {
  new GsonBuilder()
    .registerTypeAdapter(classOf[ArrayBuffer[Name]], new ArrayBufferSerializer[Name]())
    .serializeNulls()
    .create()
    .toJson(this)
}

This produces the result you're looking for:

{"names":[{"firstName":"John","middleName":null,"lastName":"Smith"}],"phone":null}