package serializers.json; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.ContentHandler; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import serializers.*; import data.media.Image; import data.media.Media; import data.media.MediaContent; /** * Driver that uses JSON.simple [http://code.google.com/p/json-simple/], with manual parsing with a ContentHandler. */ public class JsonSimpleWithContentHandler { public static void register(TestGroups groups) { groups.media.add(JavaBuiltIn.mediaTransformer, new SemiManualSerializer("json/json.simple/manual"), new SerFeatures( SerFormat.JSON, SerGraph.FLAT_TREE, SerClass.MANUAL_OPT, "" ) ); } static class SemiManualSerializer extends Serializer<MediaContent> { private final String name; private final JSONParser parser; private final MediaContentTransformer transformer; public SemiManualSerializer(String name) { this.name = name; this.parser = new JSONParser(); this.transformer = new MediaContentTransformer(); } public String getName() { return name; } public MediaContent deserialize(byte[] array) throws Exception { String mediaContentJsonInput = new String(array, "UTF-8"); return readMediaContent(parser, transformer, mediaContentJsonInput); } public byte[] serialize(MediaContent mediaContent) throws Exception { StringWriter writer = new StringWriter(); writeMediaContent(writer, mediaContent); writer.flush(); return writer.toString().getBytes("UTF-8"); } private static MediaContent readMediaContent(JSONParser parser, MediaContentTransformer transformer, String mediaContentJsonInput) throws Exception { parser.parse(mediaContentJsonInput, transformer); return transformer.getResult(); } @SuppressWarnings("unchecked") private static JSONObject createJsonObject(Media media) { JSONObject jsonObject = new JSONObject(); if (media.hasBitrate) { jsonObject.put("bitrate", media.bitrate); } jsonObject.put("copyright", media.copyright); jsonObject.put("duration", media.duration); jsonObject.put("format", media.format); jsonObject.put("height", media.height); int size = media.persons.size(); JSONArray personsJsonArray = new JSONArray(); for (int i = 0; i < size; i++) { personsJsonArray.add(media.persons.get(i)); } jsonObject.put("persons", personsJsonArray); jsonObject.put("player", media.player.name()); jsonObject.put("size", media.size); jsonObject.put("title", media.title); jsonObject.put("uri", media.uri); jsonObject.put("width", media.width); return jsonObject; } @SuppressWarnings("unchecked") private static JSONObject createJsonObject(Image image) { JSONObject jsonObject = new JSONObject(); jsonObject.put("height", image.height); jsonObject.put("size", image.size.name()); jsonObject.put("title", image.title); jsonObject.put("uri", image.uri); jsonObject.put("width", image.width); return jsonObject; } @SuppressWarnings("unchecked") private static void writeMediaContent(Writer writer, MediaContent mediaContent) throws Exception { JSONObject jsonObject = new JSONObject(); jsonObject.put("media", createJsonObject(mediaContent.media)); jsonObject.put("images", createJsonArray(mediaContent.images)); jsonObject.writeJSONString(writer); } @SuppressWarnings("unchecked") private static JSONArray createJsonArray(List<Image> images) { JSONArray jsonArray = new JSONArray(); for (Image image : images) { jsonArray.add(createJsonObject(image)); } return jsonArray; } private static class MediaContentTransformer implements ContentHandler { private static enum State { INIT, READING_MEDIA_CONTENT, FINAL, READING_MEDIA, READING_MEDIA_URI, READING_MEDIA_TITLE, READING_MEDIA_WIDTH, READING_MEDIA_HEIGHT, READING_MEDIA_FORMAT, READING_MEDIA_DURATION, READING_MEDIA_SIZE, READING_MEDIA_BITRATE, READING_MEDIA_PERSONS, READING_MEDIA_PERSON, READING_MEDIA_PLAYER, READING_MEDIA_COPYRIGHT, FINISHED_MEDIA, READING_IMAGES, FINISHED_IMAGES, READING_IMAGE, READING_IMAGE_URI, READING_IMAGE_TITLE, READING_IMAGE_WIDTH, READING_IMAGE_HEIGHT, READING_IMAGE_SIZE, FINISHED_IMAGE } private State state; private final MediaContent mediaContent = new MediaContent(); private Image image; public MediaContent getResult() { return mediaContent; } @Override public void startJSON() throws ParseException, IOException { state = State.INIT; } @Override public void endJSON() throws ParseException, IOException { throw new RuntimeException("unexpected state transition"); } @Override public boolean startObject() throws ParseException, IOException { switch (state) { case INIT: state = State.READING_MEDIA_CONTENT; return true; case READING_MEDIA: mediaContent.media = new Media(); return true; case READING_IMAGE: case FINISHED_IMAGE: image = new Image(); mediaContent.images.add(image); state = State.READING_IMAGE; return true; default: throw new RuntimeException("unexpected state transition"); } } @Override public boolean endObject() throws ParseException, IOException { switch (state) { case READING_MEDIA: state = State.FINISHED_MEDIA; return true; case READING_IMAGE: image = null; state = State.FINISHED_IMAGE; return true; case FINISHED_MEDIA: case FINISHED_IMAGES: state = State.FINAL; return false; default: throw new RuntimeException("unexpected state transition"); } } @Override public boolean startObjectEntry(String key) throws ParseException, IOException { switch (state) { case READING_MEDIA_CONTENT: case FINISHED_IMAGES: if ("media".equals(key)) {state = State.READING_MEDIA; return true;} case FINISHED_MEDIA: if ("images".equals(key)) {state = State.READING_IMAGES; return true;} throw new RuntimeException("unexpected state transition"); case READING_MEDIA: if ("uri".equals(key)) {state = State.READING_MEDIA_URI; return true;} if ("title".equals(key)) {state = State.READING_MEDIA_TITLE; return true;} if ("width".equals(key)) {state = State.READING_MEDIA_WIDTH; return true;} if ("height".equals(key)) {state = State.READING_MEDIA_HEIGHT; return true;} if ("format".equals(key)) {state = State.READING_MEDIA_FORMAT; return true;} if ("duration".equals(key)) {state = State.READING_MEDIA_DURATION; return true;} if ("size".equals(key)) {state = State.READING_MEDIA_SIZE; return true;} if ("bitrate".equals(key)) {state = State.READING_MEDIA_BITRATE; return true;} if ("persons".equals(key)) {state = State.READING_MEDIA_PERSONS; return true;} if ("player".equals(key)) {state = State.READING_MEDIA_PLAYER; return true;} if ("copyright".equals(key)) {state = State.READING_MEDIA_COPYRIGHT; return true;} throw new RuntimeException("unexpected state transition"); case READING_IMAGE: if ("uri".equals(key)) {state = State.READING_IMAGE_URI; return true;} if ("title".equals(key)) {state = State.READING_IMAGE_TITLE; return true;} if ("width".equals(key)) {state = State.READING_IMAGE_WIDTH; return true;} if ("height".equals(key)) {state = State.READING_IMAGE_HEIGHT; return true;} if ("size".equals(key)) {state = State.READING_IMAGE_SIZE; return true;} default: throw new RuntimeException("unexpected state transition"); } } @Override public boolean endObjectEntry() throws ParseException, IOException { switch (state) { case READING_MEDIA: return true; case FINISHED_MEDIA: return true; case READING_IMAGE: return true; case FINISHED_IMAGES: return true; default: throw new RuntimeException("unexpected state transition"); } } @Override public boolean startArray() throws ParseException, IOException { switch (state) { case READING_MEDIA_PERSONS: mediaContent.media.persons = new ArrayList<String>(); state = State.READING_MEDIA_PERSON; return true; case READING_IMAGES: mediaContent.images = new ArrayList<Image>(); state = State.READING_IMAGE; return true; default: throw new RuntimeException("unexpected state transition"); } } @Override public boolean endArray() throws ParseException, IOException { switch (state) { case READING_MEDIA_PERSON: state = State.READING_MEDIA; return true; case FINISHED_IMAGE: state = State.FINISHED_IMAGES; return true; default: throw new RuntimeException("unexpected state transition"); } } @Override public boolean primitive(Object value) throws ParseException, IOException { switch (state) { case READING_MEDIA_URI: mediaContent.media.uri = readString(value); state = State.READING_MEDIA; return true; case READING_MEDIA_TITLE: mediaContent.media.title = readString(value); state = State.READING_MEDIA; return true; case READING_MEDIA_WIDTH: mediaContent.media.width = readInt(value); state = State.READING_MEDIA; return true; case READING_MEDIA_HEIGHT: mediaContent.media.height = readInt(value); state = State.READING_MEDIA; return true; case READING_MEDIA_FORMAT: mediaContent.media.format = readString(value); state = State.READING_MEDIA; return true; case READING_MEDIA_DURATION: mediaContent.media.duration = readLong(value); state = State.READING_MEDIA; return true; case READING_MEDIA_SIZE: mediaContent.media.size = readLong(value); state = State.READING_MEDIA; return true; case READING_MEDIA_BITRATE: mediaContent.media.bitrate = readInt(value); mediaContent.media.hasBitrate = value != null; state = State.READING_MEDIA; return true; case READING_MEDIA_PERSON: mediaContent.media.persons.add(readString(value)); return true; case READING_MEDIA_PLAYER: mediaContent.media.player = Media.Player.valueOf(readString(value)); state = State.READING_MEDIA; return true; case READING_MEDIA_COPYRIGHT: mediaContent.media.copyright = readString(value); state = State.READING_MEDIA; return true; case READING_IMAGE_URI: image.uri = readString(value); state = State.READING_IMAGE; return true; case READING_IMAGE_TITLE: image.title = readString(value); state = State.READING_IMAGE; return true; case READING_IMAGE_WIDTH: image.width = readInt(value); state = State.READING_IMAGE; return true; case READING_IMAGE_HEIGHT: image.height = readInt(value); state = State.READING_IMAGE; return true; case READING_IMAGE_SIZE: image.size = Image.Size.valueOf(readString(value)); state = State.READING_IMAGE; return true; default: throw new RuntimeException("unexpected state transition"); } } private static int readInt(Object value) { if (value == null) return 0; return ((Long) value).intValue(); } private static long readLong(Object value) { if (value == null) return 0; return ((Long) value).longValue(); } private static String readString(Object value) { if (value == null) return null; return (String) value; } } } }