Skip to content

Instantly share code, notes, and snippets.

@nadako
Created January 10, 2014 21:26
Show Gist options
  • Save nadako/8362947 to your computer and use it in GitHub Desktop.
Save nadako/8362947 to your computer and use it in GitHub Desktop.
using StringTools;
/**
* Супер-принтер для JSON.
*
* От не-супер принтера его отличают две вещи:
* 1. Он делает оступы
* 2. Он сортирует поля объектов при сериализации
*
* Он был написан для того чтобы собирать дефы под разными платформами
* и везде и всегда они выглядели одинаково. Это удобно, если нужно
* посмотреть дифф собранных дефов, и увидеть только то что реально
* изменилось, а не в результате сериализации на другой платформе.
*/
class FancyJSON
{
public static function encode(obj:Dynamic):String
{
var printer = new FancyJSON();
printer.encodeValue(obj, 0);
printer.buf.addChar("\n".code);
return printer.buf.toString();
}
var tab:String;
var tabCache:Array<String>;
var buf:StringBuf;
public function new()
{
tab = " ";
tabCache = [""];
buf = new StringBuf();
}
function getTab(n:Int):String
{
return if (n < tabCache.length) tabCache[n] else tabCache[n] = getTab(n-1) + tab;
}
function encodeValue(value:Dynamic, depth:Int):Void
{
if (Std.is(value, Float) || Std.is(value, Bool))
{
buf.add(value);
}
else if (Std.is(value, Array))
{
encodeArray(value, depth + 1);
}
else if (Std.is(value, String))
{
buf.addChar('"'.code);
buf.add(Std.string(value).replace("\\","\\\\").replace("\n","\\n").replace("\r","\\r").replace('"','\\"'));
buf.addChar('"'.code);
}
else if (Reflect.isObject(value))
{
encodeObject(value,depth+1);
}
else
{
throw 'Unsupported field type: $value';
}
}
function encodeObject(obj:Dynamic, depth:Int):Void
{
var fields = Reflect.fields(obj);
fields.sort(Reflect.compare);
var tab = getTab(depth);
var len = fields.length;
var last = len - 1;
buf.addChar("{".code);
for (i in 0...len)
{
if (i > 0) buf.add(",\n") else buf.addChar("\n".code);
buf.add(tab);
var field = fields[i];
buf.addChar('"'.code);
buf.add(field);
buf.add('": ');
encodeValue(Reflect.field(obj, field), depth);
if (i == last)
{
buf.addChar("\n".code);
buf.add(getTab(depth-1));
}
}
buf.addChar("}".code);
}
function encodeArray(obj:Array<Dynamic>, depth:Int):Void
{
buf.addChar("[".code);
var tab = getTab(depth);
var len = obj.length;
var last = len - 1;
for (i in 0...len)
{
if (i > 0) buf.add(",\n") else buf.addChar("\n".code);
buf.add(tab);
encodeValue(obj[i], depth);
if (i == last)
{
buf.addChar("\n".code);
buf.add(getTab(depth - 1));
}
}
buf.addChar("]".code);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment