Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules/
build/
temp-docs/
tests/build
.DS_Store

Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ node_js:

script:
- yarn test
- yarn docs
175 changes: 102 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,61 @@
# assemblyscript-json

![npm version](https://img.shields.io/npm/v/assemblyscript-json) ![npm downloads per month](https://img.shields.io/npm/dm/assemblyscript-json)

JSON encoder / decoder for AssemblyScript.

Special thanks to https://github.com/MaxGraey/bignum.wasm for basic unit testing infra for AssemblyScript.

# Limitations
## Installation

`assemblyscript-json` is available as a [npm package](https://www.npmjs.com/package/assemblyscript-json). You can install `assemblyscript-json` in your AssemblyScript project by running:

This is developed for use in smart contracts written in AssemblyScript for https://github.com/nearprotocol/nearcore.
This imposes such limitations:
`npm install --save assemblyscript-json`

- Float numbers not supported
- We assume that memory never needs to be deallocated (cause these contracts are short-lived).
## Usage

Note that this mostly just defines the way it's currently implemented. Contributors are welcome to fix limitations.
### Parsing JSON

# Usage
```typescript
import { JSON } from "assemblyscript-json";

## Encoding JSON
// Parse an object using the JSON object
let jsonObj: JSON.Obj = <JSON.Obj>(JSON.parse('{"hello": "world", "value": 24}'));

```ts
// Make sure memory allocator is available
import "allocator/arena";
// Import encoder
import { JSONEncoder } from "path/to/module";
// We can then use the .getX functions to read from the object if you know it's type
// This will return the appropriate JSON.X value if the key exists, or null if the key does not exist
let worldOrNull: JSON.Str | null = jsonObj.getString("hello"); // This will return a JSON.Str or null
if (worldOrNull != null) {
// use .valueOf() to turn the high level JSON.Str type into a string
let world: string = worldOrNull.valueOf();
}

let numOrNull: JSON.Num | null = jsonObj.getNum("value");
if (numOrNull != null) {
// use .valueOf() to turn the high level JSON.Num type into a f64
let value: f64 = numOrNull.valueOf();
}

// If you don't know the value type, get the parent JSON.Value
let valueOrNull: JSON.Value | null = jsonObj.getValue("hello");
if (valueOrNull != null) {
let value: JSON.Value = changetype<JSON.Value>(valueOrNull);

// Next we could figure out what type we are
if(value.isString) {
// value.isString would be true, so we can cast to a string
let stringValue: string = changetype<JSON.Str>(value).toString();

// Do something with string value
}
}
```

### Encoding JSON


```typescript
import { JSONEncoder } from "assemblyscript-json";

// Create encoder
let encoder = new JSONEncoder();
Expand All @@ -37,83 +70,79 @@ encoder.popObject();
let json: Uint8Array = encoder.serialize();

// Or get serialized data as string
let jsonString: String = encoder.toString();
let jsonString: string = encoder.toString();

assert(jsonString, '"obj": {"int": 10, "str": ""}'); // True!
```

## Parsing JSON
### Custom JSON Deserializers

```ts
// Make sure memory allocator is available
import "allocator/arena";
// Import decoder
import { JSONDecoder, JSONHandler } from "path/to/module";
```typescript
import { JSONDecoder, JSONHandler } from "assemblyscript-json";

// Events need to be received by custom object extending JSONHandler.
// NOTE: All methods are optional to implement.
class MyJSONEventsHandler extends JSONHandler {
setString(name: string, value: string): void {
// Handle field
}

setBoolean(name: string, value: bool): void {
// Handle field
}

setNull(name: string): void {
// Handle field
}

setInteger(name: string, value: i32): void {
// Handle field
}

pushArray(name: string): bool {
// Handle array start
// true means that nested object needs to be traversed, false otherwise
// Note that returning false means JSONDecoder.startIndex need to be updated by handler
return true;
}

popArray(): void {
// Handle array end
}

pushObject(name: string): bool {
// Handle object start
// true means that nested object needs to be traversed, false otherwise
// Note that returning false means JSONDecoder.startIndex need to be updated by handler
return true;
}

popObject(): void {
// Handle object end
}
setString(name: string, value: string): void {
// Handle field
}

setBoolean(name: string, value: bool): void {
// Handle field
}

setNull(name: string): void {
// Handle field
}

setInteger(name: string, value: i64): void {
// Handle field
}

setFloat(name: string, value: f64): void {
// Handle field
}

pushArray(name: string): bool {
// Handle array start
// true means that nested object needs to be traversed, false otherwise
// Note that returning false means JSONDecoder.startIndex need to be updated by handler
return true;
}

popArray(): void {
// Handle array end
}

pushObject(name: string): bool {
// Handle object start
// true means that nested object needs to be traversed, false otherwise
// Note that returning false means JSONDecoder.startIndex need to be updated by handler
return true;
}

popObject(): void {
// Handle object end
}
}

// Create decoder
let decoder = new JSONDecoder<MyJSONEventsHandler>(new MyJSONEventsHandler());

// Let's assume JSON data is available in this variable
let json: Uint8Array = ...;
// Create a byte buffer of our JSON. NOTE: Deserializers work on UTF8 string buffers.
let jsonString = '{"hello": "world"}';
let jsonBuffer = Uint8Array.wrap(String.UTF8.encode(jsonString));

// Parse JSON
decoder.deserialize(json); // This will send events to MyJSONEventsHandler

decoder.deserialize(jsonBuffer); // This will send events to MyJSONEventsHandler
```

## JSON namespace
Feel free to look through the [tests](https://github.com/nearprotocol/assemblyscript-json/tree/master/assembly/__tests__) for more usage examples.

```ts
import { JSON } from "path/to/module";
## Reference Documentation

// Can use JS parse api
let jsonObj: JSON.Object = JSON.parse(`{"hello": "world"}`);
Reference API Documentation can be found in the [docs directory](./docs).

// Can then use a key to read from the object if you know it's type
let world = jsonObj.getString("hello");
## License

// If you don't know what the type of the value
let unknown = jsonObj.getValue("hello");

unknown.isString; // true;
```
[MIT](./LICENSE)
Loading