Skip to content

Commit

Permalink
Added asNumber, switched to should-test
Browse files Browse the repository at this point in the history
  • Loading branch information
pwall567 committed Dec 11, 2024
1 parent f2cccb2 commit 404c276
Show file tree
Hide file tree
Showing 27 changed files with 2,320 additions and 2,211 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

The format is based on [Keep a Changelog](http://keepachangelog.com/).

## [9.2] - 2024-12-11
### Changed
- `JSON`: added `asNumber`, `asNumberOrNull`, `asNumberOr()` and `asNumberOrError()` extension values / functions
- `JSON`, `JSONTypeException`: renamed parameter `target` to `expected`
- `JSON`: cosmetic changes to comments
- tests : switched to `should-test` library

## [9.1] - 2024-08-17
### Changed
- `JSONString`: fixed bug in `toJSON()`
Expand Down
51 changes: 29 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ JSON Kotlin core library

## Background

The input of JSON data generally consists of two main phases – parsing the input text and converting the
human-readable form into an easily navigated internal representation, and then mapping that internal form into
pre-existing data types.
The input of JSON data generally consists of two main phases:
1. parsing the input text and converting the human-readable form into an easily navigated internal structure, and
2. mapping that internal form into pre-existing data types.
Output may similarly use an intermediate form, but it is on the input side that the converted form is most useful
– it allows, for example, all of the properties of an object to be analysed before the determination of the
appropriate representation for the object.
appropriate internal representation for the object.

There are also many types of JSON processing functions that do not require mapping to a target class – they simply
require an internal representation of the JSON data.
Expand All @@ -25,21 +25,23 @@ The `kjson-core` library provides the basic functionality required to represent
- output functions to create valid JSON representations from the internal form

The library is an evolution of the [`jsonutil`](https://github.com/pwall567/jsonutil) Java library; it makes better use
of Kotlin-specific functionality like controlled nullability.
of Kotlin-specific functionality like controlled nullability, and it adds functions to simplify the navigation of the
internal structure.

## User Guide

All JSON values are represented by Kotlin objects of type `JSONValue?` – that is, they are all instances of
classes that implement the `JSONValue` interface, or in the case of the JSON “`null`” value they are `null`.
All JSON values are represented by Kotlin objects of type “`JSONValue?`” – that is, they are all
instances of classes that implement the `JSONValue` interface, or in the case of the JSON “`null`” value
they are `null`.

### `JSONValue`

The `JSONValue` interface specifies four functions:
- `appendTo()` – this appends the JSON text form of the object to a specified `Appendable`, _e.g._ a `Writer`
(when outputting JSON, it is more efficient to append to a single `Appendable`, as opposed to creating strings for
each element)
- `toJSON()` – this outputs the value in syntactically-correct JSON (a default implementation makes use of the
above `appendTo()` function)
- `toJSON()` – this creates a `String` representation of the value in syntactically-correct JSON (a default
implementation makes use of the above `appendTo()` function)
- `outputTo()` – this outputs the JSON text form of the object using an `IntConsumer` (similar to `appendTo()`,
but allowing a greater choice of output mechanism)
- `coOutputTo()` (suspend function) – non-blocking version of `outputTo()`, suitable for use in a coroutine-based
Expand Down Expand Up @@ -83,7 +85,7 @@ The value is never `null`.

In addition to implementing [`JSONPrimitive`](#jsonprimitive), the number value classes [`JSONInt`](#jsonint),
[`JSONLong`](#jsonlong) and [`JSONDecimal`](#jsondecimal) all derive from the sealed class `JSONNumber`, which itself
derives from the system class `Number`.
derives from the system class `java.lang.Number`.
This means that these classes may be used without conversion anywhere a `Number` is called for.

The `Number` class provides a set of `toInt()`, `toLong()` _etc._ functions, to which `JSONNumber` adds the following:
Expand Down Expand Up @@ -337,12 +339,13 @@ The `JSONTypeException` provides a way of reporting such errors in a consistent
the human-readable node name, the expected type, the actual value and an optional key (as described
[above](#jsonexception)).

The `JSONTypeException` constructor takes the following parameters:
The `JSONTypeException` constructor takes the following parameters, all of which are accessible as values of the
exception object:

| Name | Type | Default | Description |
|------------|--------------|----------|-----------------------------------------------------|
| `nodeName` | `String` | `"Node"` | The name of the field, _e.g._ `"Surname"` |
| `target` | `String` | | The expected type, _e.g._ `"string"` |
| `expected` | `String` | | The expected type, _e.g._ `"string"` |
| `value` | `JSONValue?` | | The actual value found |
| `key` | `Any?` | `null` | The “key” (the location in a structure) |

Expand Down Expand Up @@ -456,7 +459,7 @@ It takes the following parameters:

| Name | Type | Default | Description |
|------------|----------|----------|-----------------------------------------------------|
| `target` | `String` | | The expected type, _e.g._ `"string"` |
| `expected` | `String` | | The expected type, _e.g._ `"string"` |
| `key` | `Any?` | `null` | The “key” (the location in a structure) |
| `nodeName` | `String` | `"Node"` | The name of the field, _e.g._ `"Surname"` |

Expand All @@ -482,6 +485,7 @@ The conversion may be combined with the error reporting using the `asXxxxOrError
| `JSONValue?.asUShortOrError()` | `UShort` |
| `JSONValue?.asUByteOrError()` | `UByte` |
| `JSONValue?.asDecimalOrError()` | `BigDecimal` |
| `JSONValue?.asNumberOrError()` | `Number` |
| `JSONValue?.asBooleanOrError()` | `Boolean` |
| `JSONValue?.asArrayOrError()` | `JSONArray` |
| `JSONValue?.asObjectOrError()` | `JSONObject` |
Expand All @@ -491,8 +495,8 @@ The `asArrayOrError()` and `asObjectOrError()` functions return `JSONArray` and
of course be used as the underlying implementation types (`List` and `Map`).

The functions all take the same parameters as the `typeError()` function (which they all call if the type is not
correct), but in the case of these functions, the `target` parameter also has a default value, a string representing the
target type.
correct), but in the case of these functions, the `expected` parameter also has a default value, a string representing
the expected type.

Using these functions, the above example (for the use of `typeError`) may be written:
```kotlin
Expand Down Expand Up @@ -525,6 +529,8 @@ To simplify casting a `JSONValue` to the expected type, the `JSON` object provid
| `JSONValue?.asUByteOrNull` | `UByte?` | return `null` |
| `JSONValue?.asDecimal` | `BigDecimal` | throw `JSONTypeException` |
| `JSONValue?.asDecimalOrNull` | `BigDecimal?` | return `null` |
| `JSONValue?.asNumber` | `Number` | throw `JSONTypeException` |
| `JSONValue?.asNumberOrNull` | `Number?` | return `null` |
| `JSONValue?.asBoolean` | `Boolean` | throw `JSONTypeException` |
| `JSONValue?.asBooleanOrNull` | `Boolean?` | return `null` |
| `JSONValue?.asArray` | `JSONArray` | throw `JSONTypeException` |
Expand All @@ -533,7 +539,7 @@ To simplify casting a `JSONValue` to the expected type, the `JSON` object provid
| `JSONValue?.asObjectOrNull` | `JSONObject?` | return `null` |

The [`JSONTypeException`](#jsontypeexception) will use the default value `"Node"` for the `nodeName`, and the class name
of the target type as the default for `target`.
of the expected type as the default for `expected`.
The default value for `key` is `null`.

As with the `asXxxxOrError()` functions, the extension values representing a simple value return the actual value type,
Expand All @@ -556,6 +562,7 @@ A further way of casting a `JSONValue` to the expected type is provided by the `
| `JSONValue?.asUShortOr()` | `UShort` |
| `JSONValue?.asUByteOr()` | `UByte` |
| `JSONValue?.asDecimalOr()` | `BigDecimal` |
| `JSONValue?.asNumberOr()` | `Number` |
| `JSONValue?.asBooleanOr()` | `Boolean` |
| `JSONValue?.asArrayOr()` | `JSONArray` |
| `JSONValue?.asObjectOr()` | `JSONObject` |
Expand All @@ -566,7 +573,7 @@ This may be used to provide a default value, silently ignoring the type error, b
throw an exception.
For example:
```kotlin
node.asStringOr { typeError(target = "string", key = "/person/surname", nodeName = "Surname") }
node.asStringOr { typeError(expected = "string", key = "/person/surname", nodeName = "Surname") }
```

The advantage of using these functions as compared to `asXxxxOrError()`, is that these functions are inline, and the
Expand Down Expand Up @@ -694,25 +701,25 @@ The diagram was produced by [Dia](https://wiki.gnome.org/Apps/Dia/); the diagram

## Dependency Specification

The latest version of the library is 9.1, and it may be obtained from the Maven Central repository.
The latest version of the library is 9.2, and it may be obtained from the Maven Central repository.

### Maven
```xml
<dependency>
<groupId>io.kjson</groupId>
<artifactId>kjson-core</artifactId>
<version>9.1</version>
<version>9.2</version>
</dependency>
```
### Gradle
```groovy
implementation "io.kjson:kjson-core:9.1"
implementation "io.kjson:kjson-core:9.2"
```
### Gradle (kts)
```kotlin
implementation("io.kjson:kjson-core:9.1")
implementation("io.kjson:kjson-core:9.2")
```

Peter Wall

2024-08-17
2024-12-11
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>kjson-core</artifactId>
<version>9.1</version>
<version>9.2</version>
<name>JSON Kotlin core functionality</name>
<description>JSON Kotlin core functionality</description>
<packaging>jar</packaging>
Expand Down Expand Up @@ -99,6 +99,12 @@
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>io.kstuff</groupId>
<artifactId>should-test</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.pwall.json</groupId>
<artifactId>json-simple</artifactId>
Expand Down
Loading

0 comments on commit 404c276

Please sign in to comment.