Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/json2object/utils/TypeTools.hx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ class TypeTools {

#if macro

public static function isMap(type:Type):Bool {
var t = follow(type);
switch (t) {
case TAbstract(_.get() => a, [keyType, valueType]):
if (a.pack.join(".") == "haxe.ds" && a.name == "Map") return true;
else return false;

case TInst(_.get() => c, [keyType, valueType]):
for (i in c.interfaces)
if (i.t.get().pack.join(".") == "haxe" && i.t.get().name == "IMap") return true;
return false;

default:
return false;
}
}


public static inline function toComplexType(type:Null<Type>):Null<ComplexType> {
return {
inline function direct()
Expand Down
102 changes: 92 additions & 10 deletions src/json2object/writer/DataBuilder.hx
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,32 @@ class DataBuilder {
}

return macro {
order = order ?? [];

var indent = buildIndent(space, level);
var firstIndent = (indentFirst) ? indent : '';
if (o == null) { return firstIndent + "null"; }
var valueWriter = new $clsValue(ignoreNullOptionals);

@:privateAccess {
var values = [for (key in o.keys()) indent + space + '"'+key+'": '+valueWriter._write(o.get(key), space, level + 1, false, onAllOptionalNull)];
var values = [
for (key in order)
if (o.exists(key))
indent + space + '"'+key+'": '+valueWriter._write(o.get(key), space, level + 1, false, onAllOptionalNull)
];

var remainingKeys = [
for (key in o.keys())
if (!order.contains(key))
key
];
remainingKeys.sort(Reflect.compare);

values = values.concat([
for (key in remainingKeys)
indent + space + '"'+key+'": '+valueWriter._write(o.get(key), space, level + 1, false, onAllOptionalNull)
]);

var newLine = (space != '' && values.length > 0) ? '\n' : '';

var json = firstIndent+'{' + newLine;
Expand Down Expand Up @@ -163,7 +182,8 @@ class DataBuilder {
}

var assignations:Array<Expr> = [];
var skips: Array<Expr> = [];
var nullSkips: Array<Expr> = [];
var defaultSkips: Array<Expr> = [];

for (field in fields) {
if (field.meta.has(":jignored")) { continue; }
Expand Down Expand Up @@ -205,6 +225,9 @@ class DataBuilder {
} else if (field.meta.has(":noquoting")) {
assignation = macro $assignation
+ new $f_cls(ignoreNullOptionals).dontQuote()._write(cast $f_a, space, level + 1, false, onAllOptionalNull);
} else if (field.meta.has(":order")) {
var order = field.meta.extract(":order")[0].params[0];
assignation = macro $assignation + new $f_cls(ignoreNullOptionals)._write(cast $f_a, space, level + 1, false, onAllOptionalNull, $order);
} else {
assignation = macro $assignation + new $f_cls(ignoreNullOptionals)._write(cast $f_a, space, level + 1, false, onAllOptionalNull);
}
Expand All @@ -215,38 +238,90 @@ class DataBuilder {
case TAbstract(t, params):
if (t.toString() == "Null") {
// Null<Bool>
skips.push(macro $f_a == null);
nullSkips.push(macro $f_a == null);
} else {
// Bool
skips.push(macro false);
nullSkips.push(macro false);
}
default:
nullSkips.push(macro $f_a == null);
}
} else {
nullSkips.push(macro false);
}

if (field.meta.has(":default")) {
// Get the value of the @:default annotation.
var f_default:Expr = macro ${field.meta.extract(":default")[0].params[0]};

switch (f_default.expr) {
case ECall(e, params):
// You cannot directly compare enums with arguments.
// Here, we don't skip the value, and assume @:jcustomparse will handle converting to a primative.
defaultSkips.push(macro false);
case EArrayDecl(values):
if (field.type.isMap()) {
var f_shouldskip:Expr = values.length == 0 ? macro !$f_a.keys().hasNext() : macro {
var defaultMap = $f_default; // store in local variable to avoid multiple evaluation
var skip:Bool = true;
for (k in $f_a.keys()) {
if (!defaultMap.exists(k) || $f_a.get(k) != defaultMap.get(k)) {
skip = false;
break;
}
}
skip;
}
defaultSkips.push(f_shouldskip);
} else {
var f_shouldskip:Expr = macro $f_a.length == $f_default.length ? {
var defaultArray = $f_default; // store in local variable to avoid multiple evaluation
var skip:Bool = true;
for (i in 0...$f_a.length) {
if ($f_a[i] != defaultArray[i]) {
skip = false;
break;
}
}
skip;
} : false;
defaultSkips.push(f_shouldskip);
}
default:
skips.push(macro $f_a == null);
// Compare the default value with the value of the field.
// If the values are the same, skip the value.
var f_shouldskip:Expr = macro $f_a == $f_default;
defaultSkips.push(f_shouldskip);
}
} else {
skips.push(macro false);
// Never skip if there is no @:default annotation.
defaultSkips.push(macro false);
}

default:
}
}
var array = {expr:EArrayDecl(assignations), pos:Context.currentPos()};
var skips = {expr:EArrayDecl(skips), pos:Context.currentPos()};
var nullSkips = {expr:EArrayDecl(nullSkips), pos:Context.currentPos()};
var defaultSkips = {expr:EArrayDecl(defaultSkips), pos:Context.currentPos()};

return macro {
var indent = buildIndent(space, level);
var firstIndent = (indentFirst) ? indent : '';
if (o == null) { return firstIndent + "null"; }
@:privateAccess{
var decl = ${array};
var defaultSkips = ${defaultSkips};
if (ignoreNullOptionals) {
var skips = ${skips};
if (skips.indexOf(false) == -1) {
var nullSkips = ${nullSkips};
if (nullSkips.indexOf(false) == -1) {
decl = onAllOptionalNull != null ? [onAllOptionalNull()] : [];
}
else {
decl = [ for (i in 0...decl.length) skips[i] ? continue : decl[i]];
decl = [ for (i in 0...decl.length) (nullSkips[i] || defaultSkips[i]) ? continue : decl[i]];
}
} else {
decl = [ for (i in 0...decl.length) (defaultSkips[i]) ? continue : decl[i]];
}
var newLine = (space != '' && decl.length > 0) ? '\n' : '';

Expand Down Expand Up @@ -415,6 +490,9 @@ class DataBuilder {
}
};

var isMapWriter:Bool = false;
var mapKey:Null<ComplexType> = null;

var writeExpr = switch (type) {
case TInst(_.get()=>t, p) :
switch(t.module) {
Expand Down Expand Up @@ -461,6 +539,8 @@ class DataBuilder {
}
}
else if (t.module == #if (haxe_ver >= 4) "haxe.ds.Map" #else "Map" #end) {
isMapWriter = true;
mapKey = p[0].toComplexType();
makeMapWriter(p[0], p[1], c);
}
else {
Expand Down Expand Up @@ -492,6 +572,8 @@ class DataBuilder {
{name:"indentFirst", meta:null, opt:false, type:Context.getType("Bool").toComplexType(), value:macro false},
{name:"onAllOptionalNull", meta:null, opt:true, type:onAllOptionalNullCT, value: macro null}
];
if(isMapWriter)
args.push({name:"order", meta:null, opt:true, type:(macro: Array<$mapKey>), value:macro null});
var privateWrite:Field = {
doc: null,
kind: FFun({args:args, expr:writeExpr, params:null, ret:null}),
Expand Down