package serializers.json; import static data.media.FieldMapping.*; import java.io.*; import java.util.ArrayList; import java.util.List; import serializers.*; import com.google.gson.stream.*; import data.media.Image; import data.media.Media; import data.media.MediaContent; /** * Driver that uses the new streaming parser of GSON, with fully * manual data binding for optimal performance. */ public class JsonGsonManual { public static void register(TestGroups groups) { groups.media.add(JavaBuiltIn.mediaTransformer, new ManualSerializer("json/gson/manual"), new SerFeatures( SerFormat.JSON, SerGraph.FLAT_TREE, SerClass.MANUAL_OPT, "" ) ); } // ------------------------------------------------------------ // Serializer (just one) static class ManualSerializer extends Serializer<MediaContent> { private final String name; public ManualSerializer(String name) { this.name = name; } public String getName() { return name; } public MediaContent deserialize(byte[] array) throws Exception { Reader r = new StringReader(new String(array, "UTF-8")); JsonReader reader = new JsonReader(r); MediaContent content = readMediaContent(reader); r.close(); return content; } public byte[] serialize(MediaContent data) throws IOException { StringWriter w = new StringWriter(); JsonWriter writer = new JsonWriter(w); writeMediaContent(writer, data); writer.close(); w.flush(); return w.toString().getBytes("UTF-8"); } // // // Read methods protected MediaContent readMediaContent(JsonReader parser) throws IOException { MediaContent mc = new MediaContent(); if (parser.peek() != JsonToken.BEGIN_OBJECT) { reportIllegal(parser, JsonToken.BEGIN_OBJECT); } parser.beginObject(); // loop for main-level fields JsonToken t; while ((t = parser.peek()) != JsonToken.END_OBJECT) { if (t != JsonToken.NAME) { reportIllegal(parser, JsonToken.NAME); } String field = parser.nextName(); Integer I = fullFieldToIndex.get(field); if (I != null) { switch (I) { case FIELD_IX_MEDIA: mc.media = readMedia(parser); continue; case FIELD_IX_IMAGES: if (parser.peek() != JsonToken.BEGIN_ARRAY) { reportIllegal(parser, JsonToken.BEGIN_ARRAY); } parser.beginArray(); List<Image> images = new ArrayList<Image>(); while (parser.peek() == JsonToken.BEGIN_OBJECT) { parser.beginObject(); images.add(readImage(parser)); } parser.endArray(); mc.images = images; continue; } } throw new IllegalStateException("Unexpected field '"+field+"'"); } parser.endObject(); if (mc.media == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_MEDIA); if (mc.images == null) mc.images = new ArrayList<Image>(); return mc; } private Media readMedia(JsonReader parser) throws IOException { if (parser.peek() != JsonToken.BEGIN_OBJECT) { reportIllegal(parser, JsonToken.BEGIN_OBJECT); } parser.beginObject(); Media media = new Media(); JsonToken t; boolean haveWidth = false; boolean haveHeight = false; boolean haveDuration = false; boolean haveSize = false; while ((t = parser.peek()) != JsonToken.END_OBJECT) { if (t != JsonToken.NAME) { reportIllegal(parser, JsonToken.NAME); } // read value token (or BEGIN_ARRAY) String field = parser.nextName(); Integer I = fullFieldToIndex.get(field); if (I != null) { switch (I) { case FIELD_IX_PLAYER: media.player = Media.Player.valueOf(parser.nextString()); continue; case FIELD_IX_URI: media.uri = parser.nextString(); continue; case FIELD_IX_TITLE: media.title = parser.nextString(); continue; case FIELD_IX_WIDTH: media.width = parser.nextInt(); haveWidth = true; continue; case FIELD_IX_HEIGHT: media.height = parser.nextInt(); haveHeight = true; continue; case FIELD_IX_FORMAT: media.format = parser.nextString(); continue; case FIELD_IX_DURATION: media.duration = parser.nextLong(); haveDuration = true; continue; case FIELD_IX_SIZE: media.size = parser.nextLong(); haveSize = true; continue; case FIELD_IX_BITRATE: media.bitrate = parser.nextInt(); media.hasBitrate = true; continue; case FIELD_IX_PERSONS: if (parser.peek() != JsonToken.BEGIN_ARRAY) { reportIllegal(parser, JsonToken.BEGIN_ARRAY); } parser.beginArray(); List<String> persons = new ArrayList<String>(); while (parser.peek() != JsonToken.END_ARRAY) { persons.add(parser.nextString()); } parser.endArray(); media.persons = persons; continue; case FIELD_IX_COPYRIGHT: media.copyright = parser.nextString(); continue; } } throw new IllegalStateException("Unexpected field '"+field+"'"); } parser.endObject(); if (media.uri == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_URI); if (!haveWidth) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_WIDTH); if (!haveHeight) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_HEIGHT); if (media.format == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_FORMAT); if (!haveDuration) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_DURATION); if (!haveSize) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_SIZE); if (media.persons == null) media.persons = new ArrayList<String>(); if (media.player == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_PLAYER); return media; } private Image readImage(JsonReader parser) throws IOException { JsonToken t; Image image = new Image(); boolean haveWidth = false; boolean haveHeight = false; while ((t = parser.peek()) != JsonToken.END_OBJECT) { if (t != JsonToken.NAME) { reportIllegal(parser, JsonToken.NAME); } String field = parser.nextName(); Integer I = fullFieldToIndex.get(field); if (I != null) { switch (I) { case FIELD_IX_URI: image.uri = parser.nextString(); continue; case FIELD_IX_TITLE: image.title = parser.nextString(); continue; case FIELD_IX_WIDTH: image.width = parser.nextInt(); haveWidth = true; continue; case FIELD_IX_HEIGHT: image.height = parser.nextInt(); haveHeight = true; continue; case FIELD_IX_SIZE: image.size = Image.Size.valueOf(parser.nextString()); continue; } } throw new IllegalStateException("Unexpected field '"+field+"'"); } parser.endObject(); if (image.uri == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_URI); if (!haveWidth) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_WIDTH); if (!haveHeight) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_HEIGHT); if (image.size == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_SIZE); return image; } private void reportIllegal(JsonReader parser, JsonToken expToken) throws IOException { JsonToken curr = parser.peek(); String msg = "Expected token "+expToken+"; got "+curr; if (curr == JsonToken.NAME) { msg += " (current field name '"+parser.nextName()+"')"; } throw new IllegalStateException(msg); } // // // Write methods protected void writeMediaContent(JsonWriter writer, MediaContent content) throws IOException { writer.beginObject(); writeMedia(writer, content.media); writer.name(FULL_FIELD_NAME_IMAGES); writer.beginArray(); for (Image i : content.images) { writeImage(writer, i); } writer.endArray(); writer.endObject(); } private void writeMedia(JsonWriter writer, Media media) throws IOException { writer.name(FULL_FIELD_NAME_MEDIA); writer.beginObject(); writeStringField(writer, FULL_FIELD_NAME_PLAYER, media.player.name()); writeStringField(writer, FULL_FIELD_NAME_URI, media.uri); if (media.title != null) { writeStringField(writer, FULL_FIELD_NAME_TITLE, media.title); } writeIntField(writer, FULL_FIELD_NAME_WIDTH, media.width); writeIntField(writer, FULL_FIELD_NAME_HEIGHT, media.height); writeStringField(writer, FULL_FIELD_NAME_FORMAT, media.format); writeLongField(writer, FULL_FIELD_NAME_DURATION, media.duration); writeLongField(writer, FULL_FIELD_NAME_SIZE, media.size); if (media.hasBitrate) { writeIntField(writer, FULL_FIELD_NAME_BITRATE, media.bitrate); } if (media.copyright != null) { writeStringField(writer, FULL_FIELD_NAME_COPYRIGHT, media.copyright); } writer.name(FULL_FIELD_NAME_PERSONS); writer.beginArray(); for (String person : media.persons) { writer.value(person); } writer.endArray(); writer.endObject(); } private void writeStringField(JsonWriter writer, String field, String value) throws IOException { writer.name(field); writer.value(value); } private void writeIntField(JsonWriter writer, String field, int value) throws IOException { writer.name(field); writer.value(value); } private void writeLongField(JsonWriter writer, String field, long value) throws IOException { writer.name(field); writer.value(value); } private void writeImage(JsonWriter writer, Image image) throws IOException { writer.beginObject(); writeStringField(writer, FULL_FIELD_NAME_URI, image.uri); if (image.title != null) { writeStringField(writer, FULL_FIELD_NAME_TITLE, image.title); } writeIntField(writer, FULL_FIELD_NAME_WIDTH, image.width); writeIntField(writer, FULL_FIELD_NAME_HEIGHT, image.height); writeStringField(writer, FULL_FIELD_NAME_SIZE, image.size.name()); writer.endObject(); } } }