diff --git a/convex-core/src/main/java/convex/core/lang/RT.java b/convex-core/src/main/java/convex/core/lang/RT.java index 094568fde..96801b24b 100644 --- a/convex-core/src/main/java/convex/core/lang/RT.java +++ b/convex-core/src/main/java/convex/core/lang/RT.java @@ -1654,8 +1654,8 @@ public static T jvm(ACell o) { * - Characters become a String * - Blobs become a hex string representation '0x....' * - * @param o Value to convert to JVM type - * @return Java value which represents JSON object + * @param o Value to convert to JSON value object + * @return Java Object which represents JSON value */ @SuppressWarnings("unchecked") public static T json(ACell o) { @@ -1672,16 +1672,7 @@ public static T json(ACell o) { return (T) (Long)((Address) o).toExactLong(); if (o instanceof AMap) { AMap m= (AMap)o; - long n=m.count(); - HashMap hm=new HashMap<>(); - for (long i=0; i me=m.entryAt(i); - ACell k=me.getKey(); - String sk=(k instanceof AString)?k.toString():RT.toString(k); - Object v=json(me.getValue()); - hm.put(sk, v); - } - return (T) hm; + return (T)jsonMap(m); } if (o instanceof ASequence) { ASequence seq= (ASequence)o; @@ -1695,9 +1686,38 @@ public static T json(ACell o) { return (T) list; } - return (T) o.toString(); } + + /** + * Converts a CVM Map to a JSON representation + * @param m Map to convert to JSON representation + * @return Java value which represents JSON object + */ + public static HashMap jsonMap(AMap m) { + int n=m.size(); + HashMap hm=new HashMap(n); + for (long i=0; i me=m.entryAt(i); + ACell k=me.getKey(); + String sk=jsonKey(k); + Object v=json(me.getValue()); + hm.put(sk, v); + } + return hm; + } + + /** + * Gets a String from a value suitable for use as a JSON map key + * @param k Value to convert to a JSON key + * @return String usable as JSON key + */ + public static String jsonKey(ACell k) { + if (k instanceof AString) return k.toString(); + if (k instanceof Keyword) return ((Keyword)k).getName().toString(); + return RT.toString(k); + } + /** * Get the runtime Type of any CVM value diff --git a/convex-core/src/main/java/convex/core/transactions/Transactions.java b/convex-core/src/main/java/convex/core/transactions/Transactions.java new file mode 100644 index 000000000..bd1bc4276 --- /dev/null +++ b/convex-core/src/main/java/convex/core/transactions/Transactions.java @@ -0,0 +1,14 @@ +package convex.core.transactions; + +import java.util.HashMap; + +import convex.core.lang.RT; + +public class Transactions { + + public static HashMap toJSON(ATransaction tx) { + HashMap result= RT.jsonMap(tx); + result.put("type", tx.getClass().getSimpleName()); + return result; + } +} diff --git a/convex-core/src/test/java/convex/core/TransactionTest.java b/convex-core/src/test/java/convex/core/TransactionTest.java index cbeea38a6..5a3310edf 100644 --- a/convex-core/src/test/java/convex/core/TransactionTest.java +++ b/convex-core/src/test/java/convex/core/TransactionTest.java @@ -5,6 +5,8 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.HashMap; + import org.junit.jupiter.api.Test; import convex.core.data.AVector; @@ -18,7 +20,9 @@ import convex.core.lang.Symbols; import convex.core.transactions.ATransaction; import convex.core.transactions.Call; +import convex.core.transactions.Invoke; import convex.core.transactions.Multi; +import convex.core.transactions.Transactions; import convex.core.transactions.Transfer; import static convex.test.Assertions.*; @@ -56,6 +60,13 @@ public void testTransfer() { doTransactionTests(t1); } + @Test public void testJSON() { + Invoke tx=Invoke.create(VILLAIN, 1, "(+ 2 3)"); + HashMap hm=Transactions.toJSON(tx); + assertEquals("Invoke",hm.get("type")); + assertEquals(1L,hm.get("sequence")); + } + @Test public void testMulti() { Transfer t1=Transfer.create(HERO, 120, VILLAIN, 1000); diff --git a/convex-core/src/test/java/convex/core/lang/RTTest.java b/convex-core/src/test/java/convex/core/lang/RTTest.java index 5e357fe9a..a523119ca 100644 --- a/convex-core/src/test/java/convex/core/lang/RTTest.java +++ b/convex-core/src/test/java/convex/core/lang/RTTest.java @@ -97,6 +97,10 @@ public void testJSON() { assertEquals("foo",RT.json(Symbols.FOO)); assertEquals(":foo",RT.json(Keywords.FOO)); + // Note keywords get colon removed when used as JSON key + assertEquals(":bar",RT.jsonMap(Maps.of(Keywords.FOO, Keywords.BAR)).get("foo")); + + // JSON should convert keys to strings assertEquals(Maps.of("1",2), RT.cvm(RT.json(Maps.of(1,2)))); assertEquals(Maps.of("[]",3), RT.cvm(RT.json(Maps.of(Vectors.empty(),3))));