Netty-socketio Overview
===
This project is an open-source Java implementation of [Socket.IO](http://socket.io/) server. Based on [Netty](http://netty.io/) server framework.

Licensed under the Apache License 2.0.

Features
================================
* __1.x - 4.x__ version of [Socket.IO-client](https://github.com/socketio/socket.io-client) is supported
* Supports xhr-polling transport
* Supports websocket transport
* Supports namespaces and rooms
* Supports ack (acknowledgment of received data)
* Supports SSL
* Supports client store (Memory, [Redisson](https://redisson.org), [Hazelcast](https://www.hazelcast.com/))
* Supports distributed broadcast across netty-socketio nodes ([Redisson](https://redisson.org), [Hazelcast](https://www.hazelcast.com/))
* Supports OSGi
* Supports Spring
* Contains Java module info for JPMS.
* Lock-free and thread-safe implementation
* Declarative handler configuration via annotations

JAR is compatible with Java 8 but needs Java 11+ for building the module-info.

Performance
================================

Customer feedback in __2012__:
CentOS, 1 CPU, 4GB RAM runned on VM:
CPU 10%, Memory 15%
6000 xhr-long polling sessions or 15000 websockets sessions
4000 messages per second

Customer feedback in __2014__:
"To stress test the solution we run 30 000 simultaneous websocket clients and managed to peak at total of about 140 000 messages per second with less than 1 second average delay." (c) Viktor Endersz - Kambi Sports Solutions

Projects using netty-socketio
================================
Multiplayer Orchestra: [multiplayer-orchestra.com](https://multiplayer-orchestra.com/)
AVOS Cloud: [avoscloud.com](https://avoscloud.com/)
Kambi Sports Solutions: [kambi.com](http://kambi.com/)
ARSnova: [arsnova.eu](https://arsnova.eu)

Recent Releases
================================
#### Please Note: trunk is current development branch.

#### 01-Mar-2024 - version 2.0.9 released

Feature - v3/v4 parsing of multiple messages in one HTTP polling body (thanks to @unverbraucht)

Fixed - IllegalReferenceCountException error

#### 24-Jan-2024 - version 2.0.8 released

Fixed - possible OOM caused by attachments parsing

#### 23-Jan-2024 - version 2.0.7 released

Github Actions support made by @liangyuanpeng

Feature - Java module support (thanks to @unverbraucht)
Feature - AuthTokenListener added (thanks to @unverbraucht)
Feature - multi-packet separator support (thanks to @unverbraucht)

Improvement - Send Bulk leave event instead of multiple leave events on disconnect (thanks to @ksahu750)

Fixed - NPE during ack response timeout (thanks to @BlueSodaWater)
Fixed - Resource Leak in readVersion() method (thanks to @JHOANG23)

#### 24-Oct-2023 - version 2.0.6 released

Feature - added availability to add key-value pairs to socket store during authorization (thanks to @shutuper)
Feature - getRoomOperations() method with room varargs param (thanks to @shutuper)

#### 01-Jul-2023 - version 2.0.3 released
Fixed - client can't connect to non-default namespace (thanks to @lyjnew)

#### 17-May-2023 - version 2.0.2 released
Fixed - NPE in WebSocketTransport and PollingTransport (thanks to @Hunterk95)

#### 14-May-2023 - version 2.0.1 released
JDK 8 is minimum version required for usage.

Fixed - message larger than maxFramePayloadLength causes memory leak

#### 14-May-2023 - version 2.0.0 released
Feature - SocketIO 4.x protocol support (thanks to @HashZhang)

Fixed - add all the socketio specific classes to bundles (thanks to @rishabhgup)

#### 17-Apr-2023 - version 1.7.25 released
Fixed - io.netty.channel.ChannelPipelineException error

#### 14-Apr-2023 - version 1.7.24 released
Feature - SocketIOClient.isWritable() method added (thanks @xuwenqing04)
Feature - Namespace.addListeners(Iterable<L> listeners) method added (thanks @damonxue)

Fixed - disconnect event packet should be a subtype of MESSAGE (thanks @MasterShi)
Fixed - BaseStoreFactory throws NPE

#### 02-Feb-2023 - version 1.7.23 released
Feature - Added support for bulk join and leave (thanks @ksahu750)

Fixed - auto disconnected (regression since 1.7.22)

#### 22-Sep-2022 - version 1.7.22 released
Feature - ping/pong support for socketio v4 protocol (thanks to @HashZhang)

#### 06-Aug-2022 - version 1.7.21 released
Fixed - transport name should be checked in uppercase (regression since 1.7.20)

#### 26-Jul-2022 - version 1.7.20 released
Feature - needClientAuth setting added (thanks to @huws)

Fixed - ContinuationWebSocketFrame should be used if payload > maxFramePayloadLength (thanks to 俞伟搏)
Fixed - event listener src class and dest bean is no match (thanks to @cifaz)
Fixed - illegal transport parameter (thanks to @mirus36)

#### 29-Apr-2021 - version 1.7.19 released
Feature - writeBufferWaterMarkLow and writeBufferWaterMarkHigh settings added (thanks to @xuminwlt)
Feature - allowHeaders setting added (thanks to @HuangHuan)
Feature - getCurrentRoomSize() method added (thanks to @sunxiaoyu3)

Fixed - namespace bug (thanks to @@johntyty912)
Fixed - multiple nodes with redisson receive same message (thanks to 梁嘉祺)
Fixed - multiple nodes receive only one LEAVE msg on client disconnect (thanks to @GaryLeung922)

#### 17-Jan-2020 - version 1.7.18 released
Feature - support for event interceptors which catch all events (thanks to @yosiat)
Fixed - namespace event broadcasting (thanks to Volodymyr Masliy)

#### 11-Jan-2019 - version 1.7.17 released
Feature - randomSession setting added to Config object (thanks to @yuanxiangz)
Fixed - NPE in WebSocketTransport
Fixed - NPE & memory leak (thanks to zhaolianwang)
Fixed - namespace parsing (thanks to Redliver)
Fixed - Redisson 3.9+ compatibility

#### 06-Jul-2018 - version 1.7.16 released
Fixed - non thread-safe ACK handling (thanks to @dawnbreaks)
Fixed - inactive long-polling channels cause memory leak (thanks to @dawnbreaks)
Fixed - websocket CloseFrame processing (thanks to @hangsu.cho)
Fixed - WebSocketTransport NPE

#### 15-May-2018 - version 1.7.15 released

Fixed - Session ID is not unique anymore
Fixed - fixed underlying connection not closing on ping timeout
Fixed - the "fin_close" problem

#### 26-Feb-2018 - version 1.7.14 released
Feature - added local socket address for the connection (thanks to @SergeyGrigorev)
Feature - `addPingListener` method added (thanks to @lovebing)
Feature - add ThreadFactory for HashedWheelTimer (thanks to @hand515)
Fixed - changed SO_LINGER to be handled as child channel (not server channel) option (thanks to @robymus)
Fixed - ByteBuf leak if binary attachments are used
Fixed - restore session from Cookie (thanks to @wuxudong)
Fixed - NumberFormatException when b64 is bool value (thanks to @vonway)
Fixed - data encoding for polling transport

#### 20-Sep-2017 - version 1.7.13 released
Feature - Added option to change the SSL KeyFactoryAlgorithm using Configuration (thanks to @robymus)
Improvement - Binary ack handling improvements (thanks to Sergey Bushik)
Fixed - Failed to mark a promise as success because it has succeeded already (thanks to @robymus)

#### 27-Aug-2016 - version 1.7.12 released
Feature - `SocketIOServer.removeAllListeners` method added
Feature - `BroadcastOperations.sendEvent` method with `excludedClient` param added
Improvement - Redisson updated to 2.4.0
Fixed - memory leak in Namespace object (thanks to @CrazyIvan007)

#### 13-Jul-2016 - version 1.7.11 released
Fixed - Throw error if transport not supported
Fixed - Client disconnecting when using Polling - IndexOutOfBoundsException

#### 4-Mar-2016 - version 1.7.10 released
Fixed - netty updated to 4.1.0.CR3 version
Fixed - binary packet parsing (thanks to Winston Li)

#### 6-Feb-2016 - version 1.7.9 released
Feature - Compression support
Fixed - DotNET client request handling
Fixed - Packet length format parsing
Fixed - skipping 'd=' in packet
Fixed - Polling clients sporadically get prematurely disconnected (thanks to lpage30)
Fixed - connections stay open forever if server sent `close` packet
Fixed - compatibility with Redisson latest version

#### 30-Nov-2015 - version 1.7.8 released
Improvement - `WebSocketServerHandshaker.allowExtensions` is `true` now
Improvement - SessionID cookie implementation (thanks to @ryandietrich)
Fixed - clientRooms leak (thanks to @andreaspalm)
Fixed - ExceptionListener not used for errors in JSON parsing
Fixed - "silent channel" attack

#### 26-Mar-2015 - version 1.6.7 released
Improvement - `useStrictOrdering` param added for websocket packets strict ordering
Improvement - `FAIL_ON_EMPTY_BEANS = false` option setted in json decoder

#### 18-Feb-2015 - version 1.7.7 released
Improvement - no need to add jackson lib if you use own JsonSupport impl
Fixed - SocketIO client 1.3.x support
Fixed - Charset encoding handling (thanks to  alim-akbashev)

#### 17-Jan-2015 - version 1.7.6 released
Improvement - `SocketIONamespace.getName()` added
Fixed - WebSocket frames aggregation
Fixed - WebSocket buffer release
Fixed - `Unexpected end-of-input in VALUE_STRING` error
Fixed - Access-Control-Allow-Credentials is TRUE for requests with origin header

#### 05-Dec-2014 - version 1.7.5 released
Feature - `Configuration.sslProtocol` param added
Fixed - BinaryEvent ack handling
Fixed - BinaryEvent non b64 encoding/decoding
Fixed - buffer leak during packet encoding

#### 15-Nov-2014 - version 1.7.4 released
Fixed - packet encoding
Fixed - BinaryEvent encoding/decoding
Fixed - unchallenged connections handling

#### 29-Sep-2014 - version 1.6.6 released
Feature - `origin` setting added
Feature - `crossDomainPolicy` setting added
Feature - `SocketIOServer.startAsync` method added

#### 24-Sep-2014 - version 1.7.3 released
Feature - Epoll support
Improvement - BinaryEvent support
Fixed - SocketIOClient disconnect handling
Fixed - broadcast callback
Fixed - NPE then no transport defined during auth
Fixed - ping timeout for polling transport
Fixed - buffer leak in PacketEncoder

#### 22-Aug-2014 - version 1.7.2 released
Fixed - wrong outgoing message encoding using websocket transport
Fixed - NPE in websocket transport
Fixed - multiple packet decoding in polling transport
Fixed - buffer leak

#### 07-Jul-2014 - version 1.7.1 released
Feature - ability to set custom `Access-Control-Allow-Origin` via Configuration.origin
Fixed - connection via CLI socket.io-client

#### 28-Jun-2014 - version 1.7.0 released
Feature - Socket.IO 1.0 protocol support. Thanks to the new protocol decoding/encoding has speedup
__Dropped__ - `SocketIOClient.sendMessage`, `SocketIOClient.sendJsonObject` methods and corresponding listeners
__Dropped__ - Flashsocket transport support
__Dropped__ - protocol version 0.7 ... 0.9.16

#### 13-May-2014 - version 1.6.5 released
Improvement - single packet encoding optimized, used mostly in WebSocket transport. Encoding time reduced up to 40% (thanks to Viktor Endersz)
Improvement - rooms handling optimized
Improvement - ExceptionListener.exceptionCaught method added
__Breaking api change__ - Configuration.autoAck replaced with ackMode
Feature - trustStore setting added
Feature - maxFramePayloadLength setting added
Feature - getAllClients and getClient methods added to SocketIONamespace
Fixed - SocketIOServer.getAllClients returns wrong clients amount

#### 25-Mar-2014 - version 1.6.4 released
Fixed - message release problem
Fixed - problem with exception listener configuration redefinition
__Breaking api change__ - DataListener.onData now throws Exception
Improvement - data parameter added to exception listener
Improvement - ability to setup socket configuration
Improvement - Configuration.autoAck parameter added

#### 06-Mar-2014 - version 1.6.3 released
Fixed - AckCallback handling during client disconnect
Fixed - unauthorized handshake HTTP code changed to 401
__Breaking api change__ - Configuration.heartbeatThreadPoolSize setting removed
Feature - annotated Spring beans support via _SpringAnnotationScanner_
Feature - common exception listener
Improvement - _ScheduledExecutorService_ replaced with _HashedWheelTimer_

#### 08-Feb-2014 - version 1.6.2 released
Fixed - wrong namespace client disconnect handling
Fixed - exception in onConnect/onDisconnect/isAuthorized methods leads to server hang
__Breaking api change__ - SocketIOClient.sendEvent methods signature changed
Improvement - multi type events support via _MultiTypeEventListener_ and _OnEvent_ annotation
Improvement - multi type events ack support via _MultiTypeAckCallback_
Improvement - SocketIOClient.getHandshakeData method added
Improvement - Jedis replaced with [Redisson](https://github.com/mrniko/redisson)

#### 14-Jan-2014 - version 1.6.1 released
Fixed - JDK 1.6+ compatibility
Feature - authorization support

#### 19-Dec-2013 - version 1.6.0 released
Fixed - XHR-pooling transport regression
Fixed - Websocket transport regression
Fixed - namespace NPE in PacketHandler
Fixed - executors shutdown during server stop
Feature - client store (Memory, [Redis](http://redis.io/), [Hazelcast](http://www.hazelcast.com/)) support
Feature - distributed broadcast across netty-socketio nodes ([Redis](http://redis.io/), [Hazelcast](http://www.hazelcast.com/)) support
Feature - OSGi support (thanks to rdevera)
Improvement - XHR-pooling optimization
Improvement - SocketIOClient.getAllRooms method added

#### 07-Dec-2013 - version 1.5.4 released
Fixed - flash policy "request leak" after page reload (thanks to ntrp)
Fixed - websocket swf loading (thanks to ntrp)
Fixed - wrong urls causes a potential DDoS
Fixed - Event.class package visibility changed to avoid direct usage
Improvement - Simplified Jackson modules registration

#### 24-Oct-2013 - version 1.5.2 released
Fixed - NPE during shutdown
Improvement - isEmpty method added to Namespace

#### 13-Oct-2013 - version 1.5.1 released
Fixed - wrong ack timeout callback invocation
Fixed - bigdecimal serialization for JSON
Fixed - infinity loop during packet handling exception
Fixed - 'client not found' handling

#### 27-Aug-2013 - version 1.5.0 released
Improvement - encoding buffers allocation optimization.
Improvement - encoding buffers now pooled in memory to reduce GC pressure (netty 4.x feature).

#### 03-Aug-2013 - version 1.0.1 released
Fixed - error on unknown property during deserialization.
Fixed - memory leak in long polling transport.
Improvement - logging error info with inbound data.

#### 07-Jun-2013 - version 1.0.0 released
First stable release.

### Maven

Include the following to your dependency list:

    <dependency>
     <groupId>com.corundumstudio.socketio</groupId>
     <artifactId>netty-socketio</artifactId>
     <version>2.0.3</version>
    </dependency>


[![Build, Test and Analyze](https://github.com/DozerMapper/dozer/actions/workflows/build.yml/badge.svg)](https://github.com/DozerMapper/dozer/actions/workflows/build.yml)
[![Release Version](https://img.shields.io/maven-central/v/com.github.dozermapper/dozer-core.svg?maxAge=2592000)](https://mvnrepository.com/artifact/com.github.dozermapper/dozer-core)
[![License](https://img.shields.io/hexpm/l/plug.svg?maxAge=2592000)]()

# Dozer

## Project Activity
The project is currently not active and will more than likely be deprecated in the future. If you are looking to use Dozer
on a greenfield project, we would discourage that. If you have been using Dozer for a while, we would suggest you start to think about migrating
onto another library, such as:
- [mapstruct](https://github.com/mapstruct/mapstruct)
- [modelmapper](https://github.com/modelmapper/modelmapper)

For those moving to mapstruct, the community has created a [Intellij plugin](https://plugins.jetbrains.com/plugin/20853-dostruct) that can help with the migration.

## Why Map?
A mapping framework is useful in a layered architecture where you are creating layers of abstraction by encapsulating changes to particular data objects vs. propagating these objects to other layers (i.e. external service data objects, domain objects, data transfer objects, internal service data objects).

Mapping between data objects has traditionally been addressed by hand coding value object assemblers (or converters) that copy data between the objects. Most programmers will develop some sort of custom mapping framework and spend countless hours and thousands of lines of code mapping to and from their different data object.

This type of code for such conversions is rather boring to write, so why not do it automatically?

## What is Dozer?
Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another, it is an open source mapping framework that is robust, generic, flexible, reusable, and configurable.

Dozer supports simple property mapping, complex type mapping, bi-directional mapping, implicit-explicit mapping, as well as recursive mapping. This includes mapping collection attributes that also need mapping at the element level.

Dozer not only supports mapping between attribute names, but also automatically converting between types. Most conversion scenarios are supported out of the box, but Dozer also allows you to specify custom conversions via XML or code-based configuration.

## Getting Started
Check out the [Getting Started Guide](https://dozermapper.github.io/gitbook/documentation/gettingstarted.html), [Full User Guide](https://dozermapper.github.io/user-guide.pdf) or [GitBook](https://dozermapper.github.io/gitbook/) for advanced information.

## Getting the Distribution
If you are using Maven, simply copy-paste this dependency to your project.

```XML
<dependency>
    <groupId>com.github.dozermapper</groupId>
    <artifactId>dozer-core</artifactId>
    <version>7.0.0</version>
</dependency>
```

## Simple Example
```XML
<mapping>
  <class-a>yourpackage.SourceClassName</class-a>
  <class-b>yourpackage.DestinationClassName</class-b>
    <field>
      <a>yourSourceFieldName</a>
      <b>yourDestinationFieldName</b>
    </field>
</mapping>
```

```Java
SourceClassName sourceObject = new SourceClassName();
sourceObject.setYourSourceFieldName("Dozer");

Mapper mapper = DozerBeanMapperBuilder.buildDefault();
DestinationClassName destObject = mapper.map(sourceObject, DestinationClassName.class);

assertTrue(destObject.getYourDestinationFieldName().equals(sourceObject.getYourSourceFieldName()));
```


JsonUnit [![Apache License 2](https://img.shields.io/badge/license-ASF2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.txt) [![Build Status](https://travis-ci.org/lukas-krecan/JsonUnit.png?branch=master)](https://travis-ci.org/lukas-krecan/JsonUnit) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.javacrumbs.json-unit/json-unit/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.javacrumbs.json-unit/json-unit)
========

JsonUnit is a library that simplifies JSON comparison in tests.

- [APIs](#apis)
  * [AssertJ integration](#assertj)
  * [Hamcrest matchers](#hamcrest)
  * [Spring MVC assertions](#spring)
  * [Spring WebTestClient](#spring-web-client)
  * [Spring REST client assertions](#spring-client)
  * [Kotest assertions](#kotest)
  * [Vintage APIs](#vintage)
- [Features](#features)
  * [JsonPath support](#jsonpath)
  * [Ignoring values](#ignorevalues)
  * [Ignoring elements](#ignoreelements)
  * [Ignoring paths](#ignorepaths)
  * [Regular expressions](#regexp)
  * [Type placeholders](#typeplc)
  * [Custom matchers](#matchers)
  * [Options](#options)
  * [Array indexing](#arrayIndexing)
  * [Numerical comparison](#numbers)
  * [Escaping dots](#dots)
  * [Lenient parsing of expected value](#lenient-parsing-of-expected-value)
  * [DifferenceListener](#differencelistener)
  * [Jackson Object Mapper customization](#jackson-object-mapper-customization)
- [Release notes](#release-notes)

# APIs
There are several different APIs you can use. They all have more or less the same features, just the usage is
slightly different.

## AssertJ integration
The recommended API is AssertJ integration which combines the power of JsonUnit and AssertJ.

```java
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.json;

...

// compares two JSON documents (note lenient parsing of expected value)
assertThatJson("{\"a\":1, \"b\":2}").isEqualTo("{b:2, a:1}");

// objects are automatically serialized before comparison
assertThatJson(jsonObject).isEqualTo("{\n\"test\": 1\n}");

// AssertJ map assertions (numbers are converted to BigDecimals)
assertThatJson("{\"a\":1}").isObject().containsEntry("a", BigDecimal.valueOf(1));

// Type placeholders
assertThatJson("{\"a\":1, \"b\": {\"c\" :3}}")
    .isObject().containsValue(json("{\"c\" :\"${json-unit.any-number}\"}"));

// AssertJ string assertion
assertThatJson("{\"a\": \"value\"")
    .node("a").isString().isEqualTo("value");

// AssertJ array assertion
assertThatJson("{\"a\":[{\"b\": 1}, {\"c\": 1}, {\"d\": 1}]}")
    .node("a").isArray().contains(json("{\"c\": 1}"));

// Can ignore array order
assertThatJson("{\"a\":[{\"b\": 1}, {\"c\": 1}, {\"d\": 1}]}")
    .when(Option.IGNORING_ARRAY_ORDER).node("a").isArray()
    .isEqualTo(json("[{\"c\": 1}, {\"b\": 1} ,{\"d\": 1}]"));

// custom matcher
assertThatJson("{\"test\":-1}")
    .withConfiguration(c -> c.withMatcher("positive", greaterThan(valueOf(0))))
    .isEqualTo("{\"test\": \"${json-unit.matches:positive}\"}");

// and
assertThatJson("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}").and(
    a -> a.node("test.a").isEqualTo(1),
    a -> a.node("test.b").isEqualTo(2)
);

// JsonPath support
assertThatJson(json)
    .inPath("$.store.book")
    .isArray()
    .contains(json(
        "            {\n" +
            "                \"category\": \"reference\",\n" +
            "                \"author\": \"Nigel Rees\",\n" +
            "                \"title\": \"Sayings of the Century\",\n" +
            "                \"price\": 8.96\n" +
            "            }"
    ));
```

JsonUnit tries to be clever when parsing the expected value. If the value can be parsed as valid JSON, it's
parsed so. If it can't be parsed, it's considered to be just a string to be compared. It usually works,
but it can lead to unexpected situations, usually with primitive values like numbers and booleans.

```java
// This test does NOT pass. "1" is parsed as JSON containing number 1, the actual value is a string.
assertThatJson("{\"id\":\"1\", \"children\":[{\"parentId\":\"1\"}]}")
    .inPath("children[*].parentId")
    .isArray()
    .containsOnly("1");

// You have to wrap the expected value by `JsonAssertions.value()`
// to prevent parsing
assertThatJson("{\"id\":\"1\", \"children\":[{\"parentId\":\"1\"}]}")
    .inPath("children[*].parentId")
    .isArray()
    .containsOnly(value("1"));

// "true" is valid JSON so it gets parsed to primitive `true`
// Have to wrap it to JsonAssertions.value() in order to make sure it's not parsed
assertThatJson("{\"root\":[\"true\"]}").node("root").isArray().containsExactly(value("true"));
```

On the other hand, if you want to make sure that the expected value is parsed as JSON, use `JsonAssertions.json()`.

### Kotlin support
Following Kotlin API is supported (notice different import)

```kotlin
// Kotlin
import net.javacrumbs.jsonunit.assertj.assertThatJson

assertThatJson("""{"root":{"a":1, "b": 2}}""") {
    isObject
    node("root.a").isEqualTo(1)
    node("root.b").isEqualTo(2)
}
```

To use AssertJ integration, import

```xml
<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit-assertj</artifactId>
    <version>3.2.7</version>
    <scope>test</scope>
</dependency>
```
For more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractAssertJTest.java).

## Hamcrests matchers
You use Hamcrest matchers in the following way

```java
import static net.javacrumbs.jsonunit.JsonMatchers.*;
import static org.junit.Assert.*;
import static net.javacrumbs.jsonunit.core.util.ResourceUtils.resource;
...

assertThat("{\"test\":1}", jsonEquals("{\"test\": 1}"));
assertThat("{\"test\":1}", jsonPartEquals("test", 1));
assertThat("{\"test\":[1, 2, 3]}", jsonPartEquals("test[0]", 1));

assertThat("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}",
    jsonEquals("{\"test\":{\"b\":2}}").when(IGNORING_EXTRA_FIELDS));

// Can use other Hamcrest matchers too
assertThat("{\"test\":1}", jsonPartMatches("test", is(valueOf(1))))

assertThat("{\"test\":1}", jsonEquals(resource("test.json")));
```

To use import
```xml
<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit</artifactId>
    <version>3.2.7</version>
    <scope>test</scope>
</dependency>
```

For more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractJsonMatchersTest.java).

## Spring MVC assertions
JsonUnit supports Spring MVC test assertions. For example

```java
import static net.javacrumbs.jsonunit.spring.JsonUnitResultMatchers.json;
...

mockMvc.perform(get("/sample").andExpect(
    json().isEqualTo("{\"result\":{\"string\":\"stringValue\", \"array\":[1, 2, 3],\"decimal\":1.00001}}")
);
mockMvc.perform(get("/sample").andExpect(
    json().node("result.string2").isAbsent()
);
mockMvc.perform(get("/sample").andExpect(
    json().node("result.array").when(Option.IGNORING_ARRAY_ORDER).isEqualTo(new int[]{3, 2, 1})
);
mockMvc.perform(get("/sample").andExpect(
    json().node("result.array").matches(everyItem(lessThanOrEqualTo(valueOf(4))))
);
```

Following Kotlin DSL is supported:

```kotlin
mockMvc.get(path).andExpect {
    jsonContent {
        node("root").isEqualTo(CORRECT_JSON)
    }
}
```

Inside `jsonContent` you have access to all AssertJ API capabilities as described [here](#assertj).

To use import
```xml
<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit-spring</artifactId>
    <version>3.2.7</version>
    <scope>test</scope>
</dependency>
```

For more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/MockMvcTest.java).

## Spring WebTestClient
To integrate with Spring WebTest client do

```java
import static net.javacrumbs.jsonunit.spring.WebTestClientJsonMatcher.json;
...

client.get().uri(path).exchange().expectBody().consumeWith(
    json().isEqualTo("{\"result\":{\"string\":\"stringValue\", \"array\":[1, 2, 3],\"decimal\":1.00001}}")
);
client.get().uri(path).exchange().expectBody().consumeWith(
    json().node("result.string2").isAbsent()
);
client.get().uri(path).exchange().expectBody().consumeWith(
    json().node("result.array").when(Option.IGNORING_ARRAY_ORDER).isEqualTo(new int[]{3, 2, 1})
);
client.get().uri(path).exchange().expectBody().consumeWith(
    json().node("result.array").matches(everyItem(lessThanOrEqualTo(valueOf(4))))
);
```

For Kotlin, you can use our bespoke DSL

```kotlin
import net.javacrumbs.jsonunit.spring.jsonContent
...
client.get().uri(path).exchange().expectBody()
    .jsonContent {
        isEqualTo(CORRECT_JSON)
    }
```

Import
```xml
<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit-spring</artifactId>
    <version>3.2.7</version>
    <scope>test</scope>
</dependency>
```

For more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/WebTestClientTest.java).

## Spring REST client assertions

```java
import static net.javacrumbs.jsonunit.spring.JsonUnitRequestMatchers.json;
...
mockServer.expect(requestTo(URI))
      .andExpect(json().isEqualTo(json))
      .andRespond(withSuccess(jsonResponse, MediaType.APPLICATION_JSON_UTF8));
```

To use import
```xml
<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit-spring</artifactId>
    <version>3.2.7</version>
    <scope>test</scope>
</dependency>
```

For more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/ClientTest.java).

## Kotest assertions
JsonUnit supports [Kotest assertions](https://kotest.io/docs/assertions/assertions.html).

Import:

```xml
<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit-kotest</artifactId>
    <version>3.2.7</version>
    <scope>test</scope>
</dependency>
```

And enjoy:

```kotlin
"""{"test":1}""" should equalJson("""{"test": 1}""")

// Provide configuration
"""{"test":1.01}""" should equalJson("""{"test":1}""", configuration { withTolerance(0.1) })

// Use inPath
"""{"test":1}""" inPath "test" should equalJson("1")

// Clues with nesting
"""{"test": {"nested": 1}}""".inPath("test").asClue {
    it inPath "nested" should equalJson("2")
}

"""{"test":1}""".inPath("test").shouldBeJsonNumber()
    // shouldBeJsonNumber returns BigDecimal, so we can use standard kotest assertions
    // PLease note that numbers are converted to BigDecimals
    .shouldBeEqualComparingTo(valueOf(1))

// The same for arrays generated by JsonPath
"""{"test": [{"a": "a"}, {"a": true}, {"a": null}, {"a": 4}]}""".inPath("$.test[*].a")
    .shouldBeJsonArray()
    .shouldContainExactly("a", true, null, valueOf(4))

// ... and objects
"""{"a":1, "b": true}""".shouldBeJsonObject().shouldMatchAll(
    "a" to { it should beJsonNumber() },
    "b" to { it should beJsonBoolean() }
)
```

See the [tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-kotest/src/test/kotlin/net/javacrumbs/jsonunit/kotest/test/KotestTest.kt) for more examples.

# Features
JsonUnit support all this features regardless of API you use.

## JsonPath support
You can use JsonPath navigation together with JsonUnit. It has native support in AssertJ integration so you can do something like this:

```java
// AssertJ style
assertThatJson(json)
    .inPath("$.store.book")
    .isArray()
    .contains(json(
        "            {\n" +
            "                \"category\": \"reference\",\n" +
            "                \"author\": \"Nigel Rees\",\n" +
            "                \"title\": \"Sayings of the Century\",\n" +
            "                \"price\": 8.96\n" +
            "            }"
    ));
```

For the other API styles you have to first import JsonPath support module
```xml
<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit-json-path</artifactId>
    <version>3.2.7</version>
    <scope>test</scope>
</dependency>
```

and then use instead of actual value

```xml
import static net.javacrumbs.jsonunit.jsonpath.JsonPathAdapter.inPath;

...
// Fluent assertions
assertThatJson(inPath(json, "$.store.book[*].author"))
    .when(Option.IGNORING_ARRAY_ORDER)
    .isEqualTo("['J. R. R. Tolkien', 'Nigel Rees', 'Evelyn Waugh', 'Herman Melville']");
```

## Ignoring values
Sometimes you need to ignore certain values when comparing. It is possible to use `${json-unit.ignore}` or `#{json-unit.ignore}`
placeholder like this

```java
// AssertJ API
assertThatJson("{\"a\":1}")
    .isEqualTo(json("{\"a\":\"${json-unit.ignore}\"}"));
```
Please note that the assertion will fail if the `test` element is missing in the actual value.

## Ignoring elements
If the element needs to be ignored completely you can use `${json-unit.ignore-element}`
placeholder.

```java
// AssertJ API
assertThatJson("{\"root\":{\"test\":1, \"ignored\": null}}")
      .isEqualTo("{\"root\":{\"test\":1, \"ignored\": \"${json-unit.ignore-element}\"}}");
```

The assertion will not fail if the element is missing in the actual value.

## Ignoring paths

`whenIgnoringPaths` configuration option makes JsonUnit ignore the specified paths in the actual value. If the path
matches, it's completely ignored. It may be missing, null or have any value. Also `when(paths(...), thenIgnore()` can be used.

```java
// AssertJ style
assertThatJson("{\"root\":{\"test\":1, \"ignored\": 1}}")
    .whenIgnoringPaths("root.ignored"))
    .isEqualTo("{\"root\":{\"test\":1}}");

// Hamcrest matcher
assertThat(
  "{\"root\":{\"test\":1, \"ignored\": 2}}",
  jsonEquals("{\"root\":{\"test\":1, \"ignored\": 1}}").whenIgnoringPaths("root.ignored")
);
```

Array index placeholder
```java
assertThatJson("[{\"a\":1, \"b\":2},{\"a\":1, \"b\":3}]")
    .whenIgnoringPaths("[*].b")
    .isEqualTo("[{\"a\":1, \"b\":0},{\"a\":1, \"b\":0}]");
```
Please note that if you use JsonPath, you should start the path to be ignored by `$`
Also note that `whenIgnoringPaths` method supports full JsonPath syntax only in AssertJ API, all the other flavors support only
exact path or array index placeholder as described above.

JsonPath with whenIgnoringPaths example:
```java
// AssertJ API
assertThatJson("{\"fields\":[" +
        "{\"key\":1, \"name\":\"AA\"}," +
        "{\"key\":2, \"name\":\"AB\"}," +
        "{\"key\":3, \"name\":\"AC\"}" +
    "]}")
    .whenIgnoringPaths("$.fields[?(@.name=='AA')].key")
    .isEqualTo("{\"fields\":[" +
        "{\"key\":2, \"name\":\"AA\"}," +
        "{\"key\":2, \"name\":\"AB\"}," +
        "{\"key\":3, \"name\":\"AC\"}" +
    "]}");
```

## Regular expressions
It is also possible to use regular expressions to compare string values

```java
assertThatJson("{\"test\": \"ABCD\"}")
    .isEqualTo("{\"test\": \"${json-unit.regex}[A-Z]+\"}");
```

For matching just part of the string, you can use this (we have to escape twice, once for Java, once for JSON)
```java
assertThatJson("{\"test\": \"This is some text followed by: ABCD, followed by this\"}")
            .isEqualTo("{\"test\": \"${json-unit.regex}^\\\\QThis is some text followed by: \\\\E[A-Z]+\\\\Q, followed by this\\\\E$\"}");
```

Since this is quite hard to write, you can implement an expression builder like
[this](https://github.com/lukas-krecan/JsonUnit/commit/75d68ef1852ade004e93ca42d676f4b996631974#diff-642a52fede8473f98c5a7b25f34c6bd68f33160cf22733127f7f7f13f3cb2fc6R713).

## Type placeholders
If you want to assert just a type, but you do not care about the exact value, you can use any-* placeholder like this

```java
assertThatJson("{\"test\":\"value\"}")
    .isEqualTo("{test:'${json-unit.any-string}'}");

assertThatJson("{\"test\":true}")
    .isEqualTo("{\"test\":\"${json-unit.any-boolean}\"}");

assertThatJson("{\"test\":1.1}")
    .isEqualTo("{\"test\":\"${json-unit.any-number}\"}");

```

You can also use hash instead of string `#{json-unit.any-string}` for example if you are using language with string interpolation
like Kotlin.

## Custom matchers
In some special cases you might want to use your own matcher in the expected document.
```java
 assertThatJson("{\"test\":-1}")
             .withMatcher("positive", greaterThan(valueOf(0)))
             .isEqualTo("{\"test\": \"${json-unit.matches:positive}\"}");
```

In even more special cases, you might want to parametrize your matcher.
```java
 Matcher<?> divisionMatcher = new DivisionMatcher();
 assertThatJson("{\"test\":5}")
    .withMatcher("isDivisibleBy", divisionMatcher)
    .isEqualTo("{\"test\": \"${json-unit.matches:isDivisibleBy}3\"}");

 private static class DivisionMatcher extends BaseMatcher<Object> implements ParametrizedMatcher {
     private BigDecimal param;

     public boolean matches(Object item) {
         return ((BigDecimal)item).remainder(param).compareTo(ZERO) == 0;
     }

     public void describeTo(Description description) {
         description.appendValue(param);
     }

     @Override
     public void describeMismatch(Object item, Description description) {
         description.appendText("It is not divisible by ").appendValue(param);
     }

     public void setParameter(String parameter) {
         this.param = new BigDecimal(parameter);
     }
 }
```
If you need a matcher with more than one parameter, you can implement it
like [this](https://stackoverflow.com/a/66183629/277042).

## Options

There are multiple options how you can configure the comparison

**TREATING_NULL_AS_ABSENT** - fields with null values are equivalent to absent fields. For example, this test passes

```java
assertThatJson("{\"test\":{\"a\":1, \"b\": null}}")
    .when(TREATING_NULL_AS_ABSENT)
    .isEqualTo("{\"test\":{\"a\":1}}");
```

**IGNORING_ARRAY_ORDER** - ignores order in arrays

```java
assertThatJson("{\"test\":[1,2,3]}")
    .when(IGNORING_ARRAY_ORDER)
    .isEqualTo("{\"test\":[3,2,1]}");
```

**IGNORING_EXTRA_ARRAY_ITEMS** - ignores unexpected array items
```java
assertThatJson("{\"test\":[1,2,3,4]}")
    .when(IGNORING_EXTRA_ARRAY_ITEMS)
    .isEqualTo("{\"test\":[1,2,3]}");

assertThatJson("{\"test\":[5,5,4,4,3,3,2,2,1,1]}")
    .when(IGNORING_EXTRA_ARRAY_ITEMS, IGNORING_ARRAY_ORDER)
    .isEqualTo("{\"test\":[1,2,3]}");
```

**IGNORING_EXTRA_FIELDS** - ignores extra fields in the compared value

```java
assertThatJson("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}")
    .when(IGNORING_EXTRA_FIELDS)
    .isEqualTo("{\"test\":{\"b\":2}}");
```

**IGNORE_VALUES** - ignores values and compares only types

```java
assertThatJson("{\"a\":2,\"b\":\"string2\"}")
    .when(paths("a", "b"), then(IGNORING_VALUES))
    .isEqualTo("{\"a\":1,\"b\":\"string\"}");
```

It is possible to combine options.

```java
assertThatJson("{\"test\":[{\"key\":3},{\"key\":2, \"extraField\":2},{\"key\":1}]}")
    .when(IGNORING_EXTRA_FIELDS, IGNORING_ARRAY_ORDER)
    .isEqualTo("{\"test\":[{\"key\":1},{\"key\":2},{\"key\":3}]}");
```

In Hamcrest assertion you can set the option like this

```java
assertThat("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}",
    jsonEquals("{\"test\":{\"b\":2}}").when(IGNORING_EXTRA_FIELDS));
```

You can define options locally (for specific paths) by using `when(path(...), then(...))`:
```java
// ignore array order for [*].a
// AssertJ
assertThatJson("{\"test\":{\"a\":1,\"b\":2,\"c\":3}}").when(paths("test.c"), then(IGNORING_VALUES))
    .isEqualTo("{\"test\":{\"a\":1,\"b\":2,\"c\":4}}");
// ignore array order everywhere but [*].b
assertThatJson("[{\"b\":[4,5,6]},{\"b\":[1,2,3]}]")
    .when(IGNORING_ARRAY_ORDER)
    .when(path("[*].b"), thenNot(IGNORING_ARRAY_ORDER))
    .isEqualTo("[{\"b\":[1,2,3]},{\"b\":[4,5,6]}]");
// ignore extra fields in the object "a"
assertThatJson("{\"a\":{\"a1\":1,\"a2\":2},\"b\":{\"b1\":1,\"b2\":2}}")
    .when(path("a"), then(IGNORING_EXTRA_FIELDS))
    .isEqualTo("{\"a\":{\"a1\":1},\"b\":{\"b1\":1}}"))
// ignore extra array items in the array
assertThatJson("{\"a\":[1,2,3]}")
    .when(path("a"), then(IGNORING_EXTRA_ARRAY_ITEMS))
    .isEqualTo("{\"a\":[1,2]}");
// Hamcrest
assertThat("{\"test\":{\"a\":1,\"b\":2,\"c\":3}}",
    jsonEquals("{\"test\":{\"a\":1,\"b\":2,\"c\":4}}").when(path("test.c"), then(IGNORING_VALUES)));

```
Note that **TREATING_NULL_AS_ABSENT** and **IGNORING_VALUES** require exact paths to ignored fields:
```java
// ignoring number and str
assertThatJson("{\"a\":2,\"b\":\"string2\"}")
    .when(paths("a", "b"), then(IGNORING_VALUES))
    .isEqualTo("{\"a\":1,\"b\":\"string\"}");
// treat null B as absent B
assertThatJson("{\"A\":1,\"B\":null}")
    .when(path("B"), then(TREATING_NULL_AS_ABSENT))
    .isEqualTo("{\"A\":1}");
```
All other options require paths to objects or arrays where values or order should be ignored.

## Array indexing
You can use negative numbers to index arrays form the end
```java
assertThatJson("{\"root\":{\"test\":[1,2,3]}}")
    .node("root.test[-1]").isEqualTo(3);
```

## Numerical comparison
Numbers are by default compared in the following way:

* If the type differs, the number is different. So 1 and 1.0 are different (int vs. float). This does not apply when Moshi is used since it [parses all numbers as Doubles](https://github.com/square/moshi/issues/192).
* Floating number comparison is exact, down to the scale - 1.0 and 1.00 are considered to be different.

You can change this behavior by setting tolerance. If you set tolerance to `0` two numbers are considered equal if they are
equal mathematically even though they have different type or precision (`a.compareTo(b) == 0`)).

```java
assertThatJson("{\"test\":1.00}").node("test").withTolerance(0).isEqualTo(1);
```

If you set tolerance to non-zero value, the values are considered equal if `abs(a-b) <= tolerance`.
```java
assertThatJson("{\"test\":1.00001}").node("test").withTolerance(0.001).isEqualTo(1);
```

Or you can use Hamcrest matcher

```java
import static java.math.BigDecimal.valueOf;
...
assertThatJson("{\"test\":1.10001}").node("test")
    .matches(closeTo(valueOf(1.1), valueOf(0.001)));
```

If you are interested why 1 and 1.0 are treated as different numbers please read this [comment](https://github.com/lukas-krecan/JsonUnit/issues/229#issuecomment-623882801).

If you want to have special handling of numerical values, you can inject your own number comparator.

```java
assertThatJson("{\"a\":1.0}")
    .withConfiguration(c -> c.withNumberComparator(numberComparator))
    .isEqualTo("{\"a\":1.00}");
```

## Escaping dots
Sometimes you have dots in JSON element names, and you need to address those elements. It is possible to escape dots like this

```java
assertThatJson("{\"name.with.dot\": \"value\"}").node("name\\.with\\.dot").isStringEqualTo("value");
```

## Lenient parsing of expected value
Writing JSON string in Java is huge pain. JsonUnit parses expected values leniently, so you do not have to quote keys,
and you can use single quotes instead of double quotes. Please note that the actual value being compared is parsed in strict mode.

```java
assertThatJson("{\"a\":\"1\", \"b\":2}").isEqualTo("{b:2, a:'1'}");
```

## Jackson Object Mapper customization
If you need to customize Jackson 2 Object Mapper, you can do using [SPI](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html).
Implement `net.javacrumbs.jsonunit.providers.Jackson2ObjectMapperProvider`.

```java
public class Java8ObjectMapperProvider implements Jackson2ObjectMapperProvider {
    private final ObjectMapper mapper;

    private final ObjectMapper lenientMapper;

    public Java8ObjectMapperProvider() {
        mapper = new ObjectMapper().registerModule(new JavaTimeModule());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        lenientMapper = new ObjectMapper().registerModule(new JavaTimeModule());
        lenientMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        lenientMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        lenientMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
    }

    @Override
    public ObjectMapper getObjectMapper(boolean lenient) {
        return lenient ? lenientMapper : mapper;
    }
}
```

and register it in `META-INF/services/net.javacrumbs.jsonunit.providers.Jackson2ObjectMapperProvider`.
See [this example](https://github.com/lukas-krecan/JsonUnit/commit/8dc7c884448c7373886dcf3b0eabfecf47c0710b).

## Logging

Although the differences are printed out by the assert statement, sometimes you use JsonUnit with other libraries like
[Jadler](https://github.com/jadler-mocking/jadler) that do not print the differences between documents. In such case, you can switch on the
logging. JsonUnit uses [SLF4J](http://www.slf4j.org/). The only thing you need to do is to configure your logging
framework to log `net.javacrumbs.jsonunit.difference` on DEBUG level.

## DifferenceListener

If you need better difference reporting, you can implement [`DifferenceListener`](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-core/src/main/java/net/javacrumbs/jsonunit/core/listener/DifferenceListener.java) and use it this way

```java
assertThatJson("{\"test\":-1}")
    .withDifferenceListener(listener)
    .isEqualTo(json);
```

## Selecting underlying library

JsonUnit is trying to cleverly match which JSON library to use. In case you need to change the default behavior, you can
use `json-unit.libraries` system property. For example `-Djson-unit.libraries=jackson2,gson`
or `System.setProperty("json-unit.libraries", "jackson2");`. Supported values are gson, json.org, moshi, jackson2

Licence
-------
JsonUnit is licensed under [Apache 2.0 licence](https://www.apache.org/licenses/LICENSE-2.0).

Release notes
=============
## 3.2.7 (2024-02-21)
* #483 More optimal fix for JsonPath arrays matching in `whenIgnoringPaths`
* Version 3.2.6 skipped due tue a mistake

## 3.2.5 (2024-02-20)
* #483 Fix JsonPath arrays matching in `whenIgnoringPaths`
* Dependency updates

## 3.2.4 (2024-02-05)
* Dependency updates
* Version 3.2.3 skipped due to release issues

## 3.2.2 (2023-09-14)
* Fix Kotest module dependencies

## 3.2.1 (2023-09-14)
* Support for Kotest
* Dependency upgrades

## 3.2.0
* Skipped for technical reasons

## 3.1.0 (2023-09-12)
* Support for custom matchers in Spring assertions
* Dependency upgrades

## 3.0.0 (2023-07-05)
* Requires Java 17
* Requires Spring 5.2 (when used with Spring)
* `Options` class hidden
* Deprecated methods and classes removed
* Dependency upgrades

## 2.38.0 (2023-05-22)
* Support for NumberComparator
* Dependency updates

## 2.37.0 (2023-03-23)
* Make custom matcher regexp DOTALL (#617)
* Dependency updates

## 2.36.1 (2023-01-29)
* #595 Fix slf4j dependency
* Dependency updates

## 2.36.0 (2022-10-05)
* Support for `node` method in JsonMapAssert #560
* Fixed number parsing in Jackson, so it works as [intended](https://github.com/lukas-krecan/JsonUnit#numbers) (see https://github.com/lukas-krecan/JsonUnit/issues/564 for details)
* Dependency updates

## 2.35.0 (2022-05-06)
* Special handling of numeric values in containsEntry #512
* Dependency updates

## 2.34.0 (2022-04-12)
* Prevent re-parsing of a value #502
* Dependency updates

## 2.33.0 (2022-04-02)
* Fixed #493 comparison of Tuples from extracting function

## 2.32.0 (2022-02-17)
* Fixed #474 ClassCastException in isArray()

## 2.31.0 (2022-02-07)
* Replaced JsonObjectAssert by JsonAssert

## 2.30.0 (2022-02-06)
* Parent type of JsonObjectAssert changed to AbstractAssert

## 2.29.0 (2022-02-05)
* #465 fixed assertion on array of objects. May introduce some backward incompatibility when using `isArray().element(i)`.
* Dependency updates

## 2.28.0

* Automatically register available Jackson 2 modules
* Dependency updates

## 2.27.0

* Made compatible with AssertJ 3.20.x - due to braking changes in AssertJ this version also **requires** AssertJ 3.20.x
  and higher.

## 2.26.0

* Fixed `containsEntries` in AssertJ object assert. This required to change the return type of `isObject()` method which
  may be an incompatible change for tests which store the result in a variable.

## 2.25.0

* Hamcrest matcher made compatible with Rest Assured #338
* Various library upgrades

## 2.24.0

* Fix OSGi configuration
* AssertJ updated to 3.19.0

## 2.23.0

* Better error message for multiple matches in isAbsent check
* Various library upgrades

## 2.22.1

* Better exception message in case of JSON that can not be parsed

## 2.22.0

* Support for Spring WebTestClient

## 2.21.0

* Fixed Kotlin AssertJ bundle #299

## 2.20.0
* assertThatJson accepts null as the actual value

## 2.19.0
* opentest4j made optional #276
* updated all dependencies

## 2.18.1
* Fix multiple `when` method application #234

## 2.18.0
* Support for URI assertions

## 2.17.0
* Do not append tolerance with zero value to diff message (thanks @valfirst)

## 2.16.2
* Fix regex issues on older Androids #227 (thanks @Sirrah)

## 2.16.1
* Add missing Kotlin classes to distribution Jars

## 2.16.0
* Kotlin DSL for AssertJ API

## 2.15.0
* Spring DSL Koltin support
* JUnit upgraded to 5.6.0

## 2.14.0
* Allow differentiating between number and integer

## 2.13.1
* Fix Jackson2NodeFactory thread safety issue in usage of ServiceLoader (thanks @cnauroth)

## 2.13.0
* Recompiled with AssertJ 3.15.0 to fix https://github.com/lukas-krecan/JsonUnit/issues/216
* (Not)Null annotations added
* Spring dependency updated to 5.2.3.RELEASE

## 2.12.0
* Updated dependencies
* Jackson node is not reparsed when compared #214

## 2.11.1
* Parse content as UTF-8 in Spring MVC test if not specified otherwise #212

## 2.11.0
* Fix Kotlin 'Inaccessible type' warning in when-path (@Vladiatro)
* Load resources as UTF-8 (@bencampion)

## 2.10.0
* Support for PathOptions
* AssertJ - support for chaining assertions in the same root
* Support for json-path in AssertJ `whenIgnoringPaths`

## 2.9.0
* Hamcrest upgraded to 2.1
* AssertJ dependency upgraded to 3.12.3 (requires AssertJ > 3.10.0)

## 2.8.1
* hamcrest-core dependency marked as required

## 2.8.0
* #185 JsonUnitRequestMatchers for client-side REST testing
* Support for array (non)emptiness in Fluent assert

## 2.7.0
* Support for Johnzon (requires 1.1.12) (thanks to elexx)

## 2.6.3
* Ignoring paths even when present in expected value #182

## 2.6.2
* Fixed AssertionErrors messages in MultipleFailuresError #181

## 2.6.1
* Path with backspaces matching fixed #176

## 2.6.0
* ${json-unit.ignore-elements} introduced

## 2.5.1
* Array comparison optimization

## 2.5.0
* Fix bug and performance issues in array comparison
* Performance optimizations

## 2.4.0
* Introduced JsonAssertions.value()
* Fixed AssertJ withFailMessage

## 2.3.0
* Support for Jackson 2 ObjectMapper customization
* Some AbstractObjectAssert marked as unsupported

## 2.2.0
* Using opentest4j
* Refactored exception reporting

## 2.1.1
* Better exception reporting
* Fixed invalid Automatic-Module-Name

## 2.0.3
* Fixed missing node handling with JsonPath
* Fixed some complex AsserJ comaprisons

## 2.0.2
* Fixed #144 (AssertJ object handling)

## 2.0.1
* Support for # instead of $ in placeholders

## 2.0.0.RC5
* More expressive Spring assertions (isNull, isNotNull, isTrue, isFalse)

## 2.0.0.RC4
* AssertJ - fix bug with '%' in error message
* Removed support for Jackson 1

## 2.0.0.RC3
* Support for and() in AssertJ assert
* asNumber() in AssertJ added
* Allow description before inPath() in AssertJ

## 2.0.0.RC2
* Fixed JsonPath bug #132
* Fixed AssertJ number comparison with Jackson 2 #130
* Fixed AssertJ asString() #131

## 2.0.0.RC1
* Depends on Java 8
* Some deprecated APis removed
* Introduces AssertJ module
* Introduces JsonPath module

Please do not hesitate to report issues.

## 1.31.0
* Introduced DifferenceContext into DifferenceListener

## 1.30.0
* Introduced DifferenceListener
* Array comparison reports extra/missing elements when comparing with array order preserved.

## 1.29.1
* Fixed error in JsonFluentAssert.ofLength error message
* Fixed matcher handling when comparing arrays #111

## 1.29.0
* [*] placeholder works even when ignoring array order

## 1.28.2
* Fixing matcher pattern

## 1.28.1
* Fixing NPE when accessing element of nonexistent array

## 1.28.0
* Support for [*] placeholder in ignored path

## 1.27.0
* Better array comparison and error messages

## 1.26.0
* IDE friendly error messages
* isStringEqualTo is chainable (thanks to @gsson)
* Dropped support of Java 5
* Automatic module names added

## 1.25.1
* Support for Jackson BinaryNode

## 1.25.0
* Support for ignoring paths whenIgnoringPaths()

## 1.24.0
* Support for parametres in custom matchers ${json-unit.matches:matcherName}param

## 1.23.0
* Support for custom matchers ${json-unit.matches:matcherName}

## 1.22.0
* Support for Moshi

## 1.21.0
* Better diff reporting for unordered arrays with single difference

## 1.20.0
* Negative array indexes added (thanks [roxspring](https://github.com/roxspring))

## 1.19.0
* isArray().thatContains(...) fluent assert added

## 1.18.0
* Resource reading helper added

## 1.17.0
* System property to specify JSON libraries to be used

## 1.16.1
* Array pattern accepts non-word characters

## 1.16.0
* isAbsent and isPresent checks take TREAT_NULL_AS_ABSENT into account

## 1.15.0
* Dependency on slf4j made optional

## 1.14.1
* Preferring org.json library to process JSONArray

## 1.14.0
* Support for org.json library
* Fix: Element out of array bounds is treated as missing

## 1.13.0
* Support for any-* placeholders

## 1.12.1
* Single quote values in expected String allowed

## 1.12.0
* Lenient parsing of expected values

## 1.11.0
* Option setting methods made deprecated if called after assertion in JsonFluentAssert
* JsonFluentAssert constructors made private. Please file an issue if you need them.

## 1.10.0
* Added support for IGNORING_EXTRA_ARRAY_ITEMS

## 1.9.0
* Made compatible with Jackson 1.4

## 1.8.0
* OSGi support thanks to @amergey

## 1.7.0
* Support for Spring MVC tests assertions

## 1.6.1
* Gson nodes are not reconverted

## 1.6.0
* Added support for Hamcrest matchers

## 1.5.6
* Fixed handling of empty value in the expected parameter

## 1.5.5
* Support for dot in node name

## 1.5.4
* Added isObject method to fluent assertions

## 1.5.3
* Jackson 1 is preferred if the serialized class contains Jackson1 annotation

## 1.5.2
*  Added support for regular expressions

## 1.5.1
* isStringEqualTo() added to fluent assertions
* isArray  added to fluent assertions

## 1.5.0
* One runtime now supports Jackson 1.x, Jackson 2.x and Gson
* Internal JsonUnit class changed in backwards incompatible way

## 1.3.0 + 0.3.0
* Options renamed
* assertJsonNot* asserts added
* Support for online configuration in Hamcrest and standard asserts added

## 1.2.0 + 0.2.0
* Error messages changed a bit when comparing structures
* Refactoring of internal classes
* Support for ignoring array order
* Support for ignoring values
* Support for ignoring extra fields

## 1.1.6 + 0.1.6
* Treat null as absent added

## 1.1.5 + 0.1.5
* Absence/presence tests added

## 1.1.4 + 0.1.4
* Path to array in root fixed

## 1.1.3 + 0.1.3
* Numeric comparison tolerance added

## 1.1.2 + 0.1.2
* jsonStringEquals and jsonStringPartEquals added

## 1.1.1 + 0.1.1
* Generics in JsonMatchers fixed

## 1.1.0 + 0.1.0
* Simplified API
* Invalid JSONs in String comparison quoted
* Runtime incompatible (compile-time compatible) changes

## 1.0.0
* Switched to Jackson 2.x
* Fluent JsonAssert renamed to JsonFluentAssert

## 0.0.16
* Fluent assertions made framework independent.

## 0.0.15
* Switched from FEST to AssertJ

## 0.0.14
* Modules refactored
* Added support for FEST assert

## 0.0.13
* Logging categories changed

## 0.0.12
* Added logging

## 0.0.11
* Ignore placeholder "${json-unit.ignore}" added

## 0.0.10
* Text differences are closed in quotes

## 0.0.9
* Matchers added

## 0.0.7
* Made Java 5 compatible

## 0.0.6
* assertJsonPartStructureEquals added

## 0.0.5
* assertJsonPartEquals added

## 0.0.4
* Better error messages in case of different types

## 0.0.3
* Support for array types and other oddities in root

## 0.0.2
* Support for nulls


## [![XChange](https://raw.githubusercontent.com/knowm/XChange/develop/etc/XChange_64_64.png)](http://knowm.org/open-source/xchange) XChange

[![Discord](https://img.shields.io/discord/778301671302365256?logo=Discord)](https://discord.gg/n27zjVTbDz)
[![Java CI with Maven on Push](https://github.com/knowm/XChange/actions/workflows/maven.yml/badge.svg?event=status)](https://github.com/knowm/XChange/actions/workflows/maven.yml)

XChange is a Java library providing a simple and consistent API for interacting with 60+ Bitcoin and other crypto currency exchanges, providing a consistent interface for trading and accessing market data.

## Important!

The world of Bitcoin changes quickly and XChange is no exception. For the latest bugfixes and features you should use the [snapshot jars](https://oss.sonatype.org/content/groups/public/org/knowm/xchange/) or build yourself from the `develop` branch. See below for more details about building with Maven. To report bugs and see what issues people are currently working on see the [issues page](https://github.com/knowm/XChange/issues).

## Description

XChange is a Java based library providing a simple and consistent API for interacting with a diverse set of crypto currency exchanges.

Basic usage is very simple: Create an `Exchange` instance, get the appropriate service, and request data. More complex usages are progressively detailed below.

## REST API
#### Public Market Data

To use public APIs which do not require authentication:

```java
Exchange bitstamp = ExchangeFactory.INSTANCE.createExchange(BitstampExchange.class);
MarketDataService marketDataService = bitstamp.getMarketDataService();
Ticker ticker = marketDataService.getTicker(CurrencyPair.BTC_USD);
System.out.println(ticker.toString());
```

#### Private Account Info

To use APIs which require authentication, create an `ExchangeSpecification` with your API credentials and pass this to `createExchange()`:

```java
ExchangeSpecification exSpec = new BitstampExchange().getDefaultExchangeSpecification();
exSpec.setUserName("34387");
exSpec.setApiKey("a4SDmpl9s6xWJS5fkKRT6yn41vXuY0AM");
exSpec.setSecretKey("sisJixU6Xd0d1yr6w02EHCb9UwYzTNuj");
Exchange bitstamp = ExchangeFactory.INSTANCE.createExchange(exSpec);
```

*Please Note:* while most exchanges use just an API key and secret key, others (such as `username` on Bitstamp or `passphrase` on Coinbase Pro) are exchange-specific. For more examples of adding the keys to the `ExchangeSpecification`, including storing them in a configuration file, see [Frequently Asked Questions](https://github.com/knowm/XChange/wiki/Frequently-Asked-Questions).

Once you have an authenticated `Exchange`, the private API services, `AccountService` and `TradeService`, can be used to access private data:

```java
// Get the account information
AccountService accountService = bitstamp.getAccountService();
AccountInfo accountInfo = accountService.getAccountInfo();
System.out.println(accountInfo.toString());
```

All exchange implementations expose the same API, but you can also directly access the underlying "raw" data from the individual exchanges if you need to.

## Websocket API

The above API is usually fully supported on all exchanges and is best used for occasional requests and polling on relatively long intervals. Many exchanges, however, heavily limit the frequency that these requests can be made, and advise instead that you use their websocket API if you need streaming or real-time data.

For a smaller number of exchanges, the websocket-based `StreamingExchange` API is also available. This uses [Reactive streams](http://reactivex.io/) to allow you to efficiently subscribe to changes relating to thousands of coin pairs without requiring large numbers of threads.

You will need to import an additional dependency for the exchange you are using (see below), then example usage is as follows:

```java
// Use StreamingExchangeFactory instead of ExchangeFactory
StreamingExchange exchange = StreamingExchangeFactory.INSTANCE.createExchange(BitstampStreamingExchange.class);

// Connect to the Exchange WebSocket API. Here we use a blocking wait.
exchange.connect().blockingAwait();

// Subscribe to live trades update.
Disposable subscription1 = exchange.getStreamingMarketDataService()
    .getTrades(CurrencyPair.BTC_USD)
    .subscribe(
        trade -> LOG.info("Trade: {}", trade),
        throwable -> LOG.error("Error in trade subscription", throwable));

// Subscribe order book data with the reference to the subscription.
Disposable subscription2 = exchange.getStreamingMarketDataService()
    .getOrderBook(CurrencyPair.BTC_USD)
    .subscribe(orderBook -> LOG.info("Order book: {}", orderBook));

// Wait for a while to see some results arrive
Thread.sleep(20000);

// Unsubscribe
subscription1.dispose();
subscription2.dispose();

// Disconnect from exchange (blocking again)
exchange.disconnect().blockingAwait();
```

Authentication, if supported for the exchange, works the same way as for the main API, via an `ExchangeSpecification`. For more information on what is supported, see the Wiki.

## More information

Now go ahead and [study some more examples](http://knowm.org/open-source/xchange/xchange-example-code), [download the thing](http://knowm.org/open-source/xchange/xchange-change-log/) and [provide feedback](https://github.com/knowm/XChange/issues).

More information about reactive streams can be found at the [RxJava wiki](https://github.com/ReactiveX/RxJava/wiki).

## Features

- [x] MIT license
- [x] consistent API across all implemented exchanges
- [x] active development
- [x] very minimal 3rd party dependencies
- [x] modular components

## More Info

Project Site: <http://knowm.org/open-source/xchange>
Example Code: <http://knowm.org/open-source/xchange/xchange-example-code>
Change Log: <http://knowm.org/open-source/xchange/xchange-change-log/>
Java Docs: <http://knowm.org/javadocs/xchange/index.html>

Talk to us on discord: [![Discord](https://img.shields.io/discord/778301671302365256?logo=Discord)](https://discord.gg/n27zjVTbDz)

## Wiki

- [Home](https://github.com/knowm/XChange/wiki)
- [FAQ](https://github.com/knowm/XChange/wiki/Frequently-Asked-Questions)
- [Design Notes](https://github.com/knowm/XChange/wiki/Design-Notes)
- [Milestones](https://github.com/knowm/XChange/wiki/Milestones)
- [Exchange Support](https://github.com/knowm/XChange/wiki/Exchange-support)
- [New Implementation Best Practices](https://github.com/knowm/XChange/wiki/New-Implementation-Best-Practices)
- [Installing SSL Certificates into TrustStore](https://github.com/knowm/XChange/wiki/Installing-SSL-Certificates-into-TrustStore)
- [Getting Started with XChange for Noobies](https://github.com/knowm/XChange/wiki/Getting-Started-with-XChange-for-Noobies)
- [Code Style](https://github.com/knowm/XChange/wiki/Code-Style)

## Continuous Integration

[![Java CI with Maven](https://github.com/knowm/XChange/actions/workflows/maven.yml/badge.svg?branch=develop&event=status)](https://github.com/knowm/XChange/actions/workflows/maven.yml)

## Getting Started

### Non-Maven

- [XChange Release Jars](http://search.maven.org/#search%7Cga%7C1%7Cknowm%20xchange)
- [XChange Snapshot Jars](https://oss.sonatype.org/content/groups/public/org/knowm/xchange/)

### Maven

The XChange release artifacts are hosted on Maven Central: [org.knowm.xchange](https://mvnrepository.com/artifact/org.knowm.xchange)

Add the following dependencies in your pom.xml file. You will need at least xchange-core. Add the additional dependencies for the exchange modules you are interested in (XYZ shown only for a placeholder). There is example code for all the modules in xchange-examples.

```xml
<dependency>
  <groupId>org.knowm.xchange</groupId>
  <artifactId>xchange-core</artifactId>
  <version>5.2.0</version>
</dependency>
<dependency>
  <groupId>org.knowm.xchange</groupId>
  <artifactId>xchange-XYZ</artifactId>
  <version>5.2.0</version>
</dependency>
```

If it is available for your exchange, you may also want to use the streaming API:

```xml
<dependency>
  <groupId>org.knowm.xchange</groupId>
  <artifactId>xchange-stream-XYZ</artifactId>
  <version>5.2.0</version>
</dependency>
```

For snapshots, add the following repository to your pom.xml file.

```xml
<repository>
  <id>sonatype-oss-snapshot</id>
  <snapshots/>
  <url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
```

The current snapshot version is:

    5.2.1-SNAPSHOT

## Building with Maven

Instruction                 | Command
--------------------------------- | ------------------------
run unit tests                    | `mvn clean test`
run unit and integration tests    | `mvn clean verify -DskipIntegrationTests=false`
install in local Maven repo       | `mvn clean install`
create project javadocs           | `mvn javadoc:aggregate`
generate dependency tree          | `mvn dependency:tree`
check for dependency updates      | `mvn versions:display-dependency-updates`
check for plugin updates          | `mvn versions:display-plugin-updates`
code format                       | `mvn com.spotify.fmt:fmt-maven-plugin:format`
pom format/organize               | `mvn com.github.ekryd.sortpom:sortpom-maven-plugin:sort`

## Bugs

Please report any bugs or submit feature requests to [XChange's Github issue tracker](https://github.com/knowm/XChange/issues).

## Contributing

If you'd like to submit a new implementation for another exchange, please take a look at [New Implementation Best Practices](https://github.com/knowm/XChange/wiki/New-Implementation-Best-Practices) first, as there are lots of time-saving tips!

For more information such as a contributor list and a list of known projects depending on XChange, visit the [Main Project Wiki](https://github.com/knowm/XChange/wiki).


# Selenide = UI Testing Framework powered by Selenium WebDriver

![Build Status](https://github.com/selenide/selenide/workflows/Run%20tests/badge.svg)
[![Maven Central](https://img.shields.io/maven-central/v/com.codeborne/selenide.svg)](https://central.sonatype.com/search?q=selenide&namespace=com.codeborne)
[![MIT License](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/selenide/selenide/blob/main/LICENSE)
![Free](https://img.shields.io/badge/free-open--source-green.svg)

[![Join the chat at https://gitter.im/codeborne/selenide](https://img.shields.io/badge/welcome%20to-chat-green.svg)](https://gitter.im/codeborne/selenide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Присоединяйся к чату https://gitter.im/codeborne/selenide-ru](https://img.shields.io/badge/%D0%B7%D0%B0%D1%85%D0%BE%D0%B4%D0%B8%20%D0%B2-%D1%87%D0%B0%D1%82-green.svg)](https://gitter.im/codeborne/selenide-ru?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Follow](https://img.shields.io/twitter/follow/selenide.svg?style=social&label=Follow)](https://twitter.com/selenide)
[![Telegram channel](https://img.shields.io/badge/Telegram-channel-blue.svg)](https://t.me/selenide)
[![Telegram чат](https://img.shields.io/badge/Telegram-%D1%87%D0%B0%D1%82-blue.svg)](https://t.me/selenide_ru)

## What is Selenide?

Selenide is a framework for writing easy-to-read and easy-to-maintain automated tests in Java.
It defines concise fluent API, natural language assertions and does some magic for ajax-based applications to let you focus entirely on the business logic of your tests.

Selenide is based on and is compatible to Selenium WebDriver 4.0+

```java
@Test
public void login() {
  open("/login");
  $(By.name("user.name")).setValue("johny");
  $("#submit").click();
  $("#username").shouldHave(text("Hello, Johny!"));
}
```

Look for [detailed comparison of Selenide and Selenium WebDriver API](https://github.com/selenide/selenide/wiki/Selenide-vs-Selenium).

#### Selenide for mobile apps
You can use Selenide for testing mobile applications. See plugin [selenide-appium](https://github.com/selenide/selenide/tree/main/modules/appium).

#### Selenide with Selenoid
You can use Selenide for running tests in Selenoid containers. See plugin [selenide-selenoid](https://github.com/selenide/selenide/tree/main/modules/selenoid).

#### Selenide with Selenium Grid
You can use Selenide for running tests in Selenium Grid. See plugin [selenide-grid](https://github.com/selenide/selenide/tree/main/modules/grid).

## Changelog

Here is [CHANGELOG](https://github.com/selenide/selenide/blob/main/CHANGELOG.md)

## How to start?

Just put selenide.jar to your project and import the following methods: `import static com.codeborne.selenide.Selenide.*;`

Look for [Quick Start](https://github.com/selenide/selenide/wiki/Quick-Start) for details.

## Resources

* First of all, [selenide.org](http://selenide.org)
* For bustlers: [How to start writing UI tests in 10 minutes](http://selenide.org/2014/10/01/how-to-start-writing-ui-tests/)
* For developers: [Selenide presentation on Devoxx 2015](http://selenide.org/2015/11/13/selenide-on-devoxx/)
* For QA engineers: [Selenide presentation on SeleniumConf 2015](http://selenide.org/2015/09/23/selenide-on-seleniumconf/)
* For russians: [Selenide presentation on SeleniumCamp 2015](http://seleniumcamp.com/materials/good-short-test/)

## FAQ

See [Frequently asked questions](http://selenide.org/faq.html)

## Posts
- Set-up environment with gradle, junit5, allure and selenide -- read a [post](https://medium.com/@rosolko/simple-allure-2-configuration-for-gradle-8cd3810658dd) on medium, grab from [GitHub](https://github.com/rosolko/allure-gradle-configuration)
- Small step do dramatically improve your tests speed -- read a [post](https://medium.com/@rosolko/boost-you-autotests-with-fast-authorization-b3eee52ecc19) on medium
- Another way to improve tests speed -- read a [post](https://medium.com/@rosolko/fast-authorization-level-local-storage-6c84e9b3cef1) on medium
- [Configure Selenide to work with Selenoid](https://medium.com/@rosolko/configure-selenide-to-work-with-selenoid-8835cd6dc7d2)

## Contributing

Contributions to Selenide are both welcomed and appreciated.
See [CONTRIBUTING.md](CONTRIBUTING.md) for specific guidelines.

Feel free to fork, clone, build, run tests and contribute pull requests for Selenide!

## Authors

Selenide was originally designed and developed by [Andrei Solntsev](http://asolntsev.github.io/) in 2011-2021
 and is maintained by [a group of enthusiast](https://github.com/orgs/selenide/people).

## Thanks

Many thanks to these incredible tools that help us create open-source software:

[![Intellij IDEA](https://selenide.org/images/jetbrains.svg)](http://www.jetbrains.com/idea)
[![BrowserStack](https://www.browserstack.com/images/mail/browserstack-logo-footer.png)](https://www.browserstack.com)
[![LambdaTest](https://www.lambdatest.com/support/img/logo.svg)](https://www.lambdatest.com/)

## License

Selenide is open-source project, and distributed under the [MIT](http://choosealicense.com/licenses/mit/) license


<img height="90" alt="Slonik Duke" align="right" src="docs/static/images/slonik_duke.png" />

# PostgreSQL JDBC Driver

PostgreSQL JDBC Driver (PgJDBC for short) allows Java programs to connect to a PostgreSQL database using standard, database independent Java code. Is an open source JDBC driver written in Pure Java (Type 4), and communicates in the PostgreSQL native network protocol.

### Status
[![GitHub CI](https://github.com/pgjdbc/pgjdbc/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/pgjdbc/pgjdbc/actions/workflows/main.yml)
[![Build status](https://ci.appveyor.com/api/projects/status/d8ucmegnmourohwu/branch/master?svg=true)](https://ci.appveyor.com/project/davecramer/pgjdbc/branch/master)
[![codecov.io](http://codecov.io/github/pgjdbc/pgjdbc/coverage.svg?branch=master)](http://codecov.io/github/pgjdbc/pgjdbc?branch=master)
[![License](https://img.shields.io/badge/License-BSD--2--Clause-blue.svg)](https://opensource.org/licenses/BSD-2-Clause)
[![Join the chat at https://gitter.im/pgjdbc/pgjdbc](https://badges.gitter.im/pgjdbc/pgjdbc.svg)](https://gitter.im/pgjdbc/pgjdbc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.postgresql/postgresql/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.postgresql/postgresql)
[![Javadocs](http://javadoc.io/badge/org.postgresql/postgresql.svg)](http://javadoc.io/doc/org.postgresql/postgresql)

## Supported PostgreSQL and Java versions
The current version of the driver should be compatible with **PostgreSQL 8.4 and higher** using the version 3.0 of the protocol and **Java 8** (JDBC 4.2) or above. Unless you have unusual requirements (running old applications or JVMs), this is the driver you should be using.

PgJDBC regression tests are run against all PostgreSQL versions since 9.1, including "build PostgreSQL from git master" version. There are other derived forks of PostgreSQL but they have not been certified to run with PgJDBC. If you find a bug or regression on supported versions, please file an [Issue](https://github.com/pgjdbc/pgjdbc/issues).

## Get the Driver
Most people do not need to compile PgJDBC. You can download the precompiled driver (jar) from the [PostgreSQL JDBC site](https://jdbc.postgresql.org/download/) or using your chosen dependency management tool:

### Maven Central
You can search on The Central Repository with GroupId and ArtifactId [org.postgresql:postgresql][mvn-search].

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.postgresql/postgresql/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.postgresql/postgresql)

```xml
<!-- Add the following dependency to your pom.xml, -->
<!-- replacing LATEST with specific version as required -->

<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
  <version>LATEST</version>
</dependency>
```

[mvn-search]: https://search.maven.org/artifact/org.postgresql/postgresql "Search on Maven Central"

#### Development snapshots
Snapshot builds (builds from `master` branch) are also deployed to OSS Sonatype Snapshot Repository, so you can test current development version (test some bugfix) by enabling the repository and using the latest [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/postgresql/postgresql/) version.

There are also available (snapshot) binary RPMs in [Fedora's Copr repository](https://copr.fedorainfracloud.org/coprs/g/pgjdbc/pgjdbc-travis/).

----------------------------------------------------
## Documentation
For more information you can read [the PgJDBC driver documentation](https://jdbc.postgresql.org/documentation/) or for general JDBC documentation please refer to [The Java™ Tutorials](http://docs.oracle.com/javase/tutorial/jdbc/).

### Driver and DataSource class

| Implements                          | Class                                          |
| ----------------------------------- | ---------------------------------------------- |
| java.sql.Driver                     | **org.postgresql.Driver**                      |
| javax.sql.DataSource                | org.postgresql.ds.PGSimpleDataSource           |
| javax.sql.ConnectionPoolDataSource  | org.postgresql.ds.PGConnectionPoolDataSource   |
| javax.sql.XADataSource              | org.postgresql.xa.PGXADataSource               |

### Building the Connection URL
The driver recognises JDBC URLs of the form:
```
jdbc:postgresql:database
jdbc:postgresql:
jdbc:postgresql://host/database
jdbc:postgresql://host/
jdbc:postgresql://host:port/database
jdbc:postgresql://host:port/
jdbc:postgresql://?service=myservice
```
The general format for a JDBC URL for connecting to a PostgreSQL server is as follows, with items in square brackets ([ ]) being optional:
```
jdbc:postgresql:[//host[:port]/][database][?property1=value1[&property2=value2]...]
```
where:
 * **jdbc:postgresql:** (Required) is known as the sub-protocol and is constant.
 * **host** (Optional) is the server address to connect. This could be a DNS or IP address, or it could be *localhost* or *127.0.0.1* for the local computer. To specify an IPv6 address your must enclose the host parameter with square brackets (jdbc:postgresql://[::1]:5740/accounting). Defaults to `localhost`.
 * **port** (Optional) is the port number listening on the host. Defaults to `5432`.
 * **database** (Optional) is the database name. Defaults to the same name as the *user name* used in the connection.
 * **propertyX** (Optional) is one or more option connection properties. For more information see *Connection properties*.

### Logging
PgJDBC uses java.util.logging for logging.
To configure log levels and control log output destination (e.g. file or console), configure your java.util.logging properties accordingly for the org.postgresql logger.
Note that the most detailed log levels, "`FINEST`", may include sensitive information such as connection details, query SQL, or command parameters.

#### Connection Properties
In addition to the standard connection parameters the driver supports a number of additional properties which can be used to specify additional driver behaviour specific to PostgreSQL™. These properties may be specified in either the connection URL or an additional Properties object parameter to DriverManager.getConnection.

| Property                      | Type |         Default         | Description                                                                                |
|-------------------------------| -- |:-----------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------    |
| user                          | String |          null           | The database user on whose behalf the connection is being made.                                                                                |
| password                      | String |          null           | The database user's password.                                                                                |
| options                       | String |          null           | Specify 'options' connection initialization parameter.                                                                                |
| service                       | String |          null           | Specify 'service' name described in pg_service.conf file. References: [The Connection Service File](https://www.postgresql.org/docs/current/libpq-pgservice.html) and [The Password File](https://www.postgresql.org/docs/current/libpq-pgpass.html). 'service' file can provide all properties including 'hostname=', 'port=' and 'dbname='. |
| ssl                           | Boolean |          false          | Control use of SSL (true value causes SSL to be required)                                                                                |
| sslfactory                    | String | org.postgresql.ssl.LibPQFactory | Provide a SSLSocketFactory class when using SSL.                                                                                |
| sslfactoryarg (deprecated)    | String |          null           | Argument forwarded to constructor of SSLSocketFactory class.                                                                                |
| sslmode                       | String |         prefer          | Controls the preference for opening using an SSL encrypted connection.                                                                                |
| sslcert                       | String |          null           | The location of the client's SSL certificate                                                                                |
| sslkey                        | String |          null           | The location of the client's PKCS#8 or PKCS#12 SSL key, for PKCS the extension must be .p12 or .pfx and the alias must be `user`                                                                                |
| sslrootcert                   | String |          null           | The location of the root certificate for authenticating the server.                                                                                |
| sslhostnameverifier           | String |          null           | The name of a class (for use in [Class.forName(String)](https://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#forName%28java.lang.String%29)) that implements javax.net.ssl.HostnameVerifier and can verify the server hostname.                                                                                |
| sslpasswordcallback           | String |          null           | The name of a class (for use in [Class.forName(String)](https://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#forName%28java.lang.String%29)) that implements javax.security.auth.callback.CallbackHandler and can handle PasswordCallback for the ssl password.                                                                     |
| sslpassword                   | String |          null           | The password for the client's ssl key (ignored if sslpasswordcallback is set)                                                                                |
| sendBufferSize                | Integer |           -1            | Socket write buffer size                                                                                |
| maxSendBufferSize             | Integer |        65536            | Maximum amount of bytes buffered before sending to the backend. pgjdbc uses `least(maxSendBufferSize, greatest(8192, SO_SNDBUF))` to determine the buffer size.                                                                                |
| receiveBufferSize             | Integer |           -1            | Socket read buffer size                                                                                |
| logServerErrorDetail          | Boolean |          true           | Allows server error detail (such as sql statements and values) to be logged and passed on in exceptions.  Setting to false will mask these errors so they won't be exposed to users, or logs.                                                                                |
| allowEncodingChanges          | Boolean |          false          | Allow for changes in client_encoding                                                                                |
| logUnclosedConnections        | Boolean |          false          | When connections that are not explicitly closed are garbage collected, log the stacktrace from the opening of the connection to trace the leak source                                                                                |
| binaryTransfer                | Boolean |          true           | Use binary format for sending and receiving data if possible. Setting this to false disables any binary transfer                                                                                |
| binaryTransferEnable          | String |           ""            | Comma separated list of types to enable binary transfer. Either OID numbers or names                                                                                |
| binaryTransferDisable         | String |           ""            | Comma separated list of types to disable binary transfer. Either OID numbers or names. Overrides values in the driver default set and values set with binaryTransferEnable.                                                                                |
| prepareThreshold              | Integer |            5            | Statement prepare threshold. A value of -1 stands for forceBinary                                                                                |
| preparedStatementCacheQueries | Integer |           256           | Specifies the maximum number of entries in per-connection cache of prepared statements. A value of 0 disables the cache.                                                                                |
| preparedStatementCacheSizeMiB | Integer |            5            | Specifies the maximum size (in megabytes) of a per-connection prepared statement cache. A value of 0 disables the cache.                                                                                |
| defaultRowFetchSize           | Integer |            0            | Positive number of rows that should be fetched from the database when more rows are needed for ResultSet by each fetch iteration                                                                                |
| loginTimeout                  | Integer |            0            | Specify how long in seconds max(2147484) to wait for establishment of a database connection.                                                                                |
| connectTimeout                | Integer |           10            | The timeout value in seconds max(2147484) used for socket connect operations.                                                                                |
| socketTimeout                 | Integer |            0            | The timeout value in seconds max(2147484) used for socket read operations.                                                                                |
| cancelSignalTimeout           | Integer |            10           | The timeout that is used for sending cancel command.                                                                                |
| sslResponseTimeout            | Integer |          5000           | Socket timeout in milliseconds waiting for a response from a request for SSL upgrade from the server.                                                                                |
| tcpKeepAlive                  | Boolean |          false          | Enable or disable TCP keep-alive.                                                                                |
| tcpNoDelay                    | Boolean |          true           | Enable or disable TCP no delay.                                                                                |
| ApplicationName               | String  | PostgreSQL JDBC Driver   | The application name (require server version >= 9.0). If assumeMinServerVersion is set to >= 9.0 this will be sent in the startup packets, otherwise after the connection is made                                                                                |
| readOnly                      | Boolean |          false          | Puts this connection in read-only mode                                                                                |
| readOnlyMode                  | String |          transaction   | Specifies the behavior when a connection is set to be read only, possible values: ignore, transaction, always                                                                                |
| disableColumnSanitiser        | Boolean |          false          | Enable optimization that disables column name sanitiser                                                                                |
| assumeMinServerVersion        | String |          null           | Assume the server is at least that version                                                                                |
| currentSchema                 | String |          null           | Specify the schema (or several schema separated by commas) to be set in the search-path                                                                                |
| targetServerType              | String |           any           | Specifies what kind of server to connect, possible values: any, master, slave (deprecated), secondary, preferSlave (deprecated), preferSecondary, preferPrimary                                                                                |
| hostRecheckSeconds            | Integer |           10            | Specifies period (seconds) after which the host status is checked again in case it has changed                                                                                |
| loadBalanceHosts              | Boolean |          false          | If disabled hosts are connected in the given order. If enabled hosts are chosen randomly from the set of suitable candidates                                                                                |
| socketFactory                 | String |          null           | Specify a socket factory for socket creation                                                                                |
| socketFactoryArg (deprecated) | String |          null           | Argument forwarded to constructor of SocketFactory class.                                                                                |
| autosave                      | String |          never          | Specifies what the driver should do if a query fails, possible values: always, never, conservative                                                                                |
| cleanupSavepoints             | Boolean |          false          | In Autosave mode the driver sets a SAVEPOINT for every query. It is possible to exhaust the server shared buffers. Setting this to true will release each SAVEPOINT at the cost of an additional round trip.                                                                                |
| preferQueryMode               | String |        extended         | Specifies which mode is used to execute queries to database, possible values: extended, extendedForPrepared, extendedCacheEverything, simple                                                                                |
| reWriteBatchedInserts         | Boolean |          false          | Enable optimization to rewrite and collapse compatible INSERT statements that are batched.                                                                                |
| escapeSyntaxCallMode          | String |         select          | Specifies how JDBC escape call syntax is transformed into underlying SQL (CALL/SELECT), for invoking procedures or functions (requires server version >= 11), possible values: select, callIfNoReturn, call                                                                                |
| maxResultBuffer               | String |          null           | Specifies size of result buffer in bytes, which can't be exceeded during reading result set. Can be specified as particular size (i.e. "100", "200M" "2G") or as percent of max heap memory (i.e. "10p", "20pct", "50percent")                                                                                |
| gssLib                        | String |          auto           | Permissible values are auto (default, see below), sspi (force SSPI) or gssapi (force GSSAPI-JSSE).                                                                                |
| gssResponseTimeout            | Integer |          5000           | Socket timeout in milliseconds waiting for a response from a request for GSS encrypted connection from the server.                                                                                |
| gssEncMode                    | String |          allow          | Controls the preference for using GSSAPI encryption for the connection, values are disable, allow, prefer, and require                                                                                |
| useSpnego                     | String |          false           | Use SPNEGO in SSPI authentication requests
| adaptiveFetch                 | Boolean |          false          | Specifies if number of rows fetched in ResultSet by each fetch iteration should be dynamic. Number of rows will be calculated by dividing maxResultBuffer size into max row size observed so far. Requires declaring maxResultBuffer and defaultRowFetchSize for first iteration.                                                             |
| adaptiveFetchMinimum          | Integer |            0            | Specifies minimum number of rows, which can be calculated by adaptiveFetch. Number of rows used by adaptiveFetch cannot go below this value.                                                                                |
| adaptiveFetchMaximum          | Integer |           -1            | Specifies maximum number of rows, which can be calculated by adaptiveFetch. Number of rows used by adaptiveFetch cannot go above this value. Any negative number set as adaptiveFetchMaximum is used by adaptiveFetch as infinity number of rows.                                                                                |
| localSocketAddress            | String |          null           | Hostname or IP address given to explicitly configure the interface that the driver will bind the client side of the TCP/IP connection to when connecting.                                                                                |
| quoteReturningIdentifiers     | Boolean |          true           | By default we double quote returning identifiers. Some ORM's already quote them. Switch allows them to turn this off                                                                                |
| authenticationPluginClassName | String |          null           | Fully qualified class name of the class implementing the AuthenticationPlugin interface. If this is null, the password value in the connection properties will be used.                                                                                |
| unknownLength                 | Integer |   Integer.MAX_LENGTH    | Specifies the length to return for types of unknown length                                                                                |
| stringtype                    | String |          null           | Specify the type to use when binding `PreparedStatement` parameters set via `setString()`                                                                                |

#### System Properties
| Property                      | Type |         Default         | Description                                                                                |
|-------------------------------| -- |:-----------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------    |
| pgjdbc.config.cleanup.thread.ttl | long | 30000 |  The driver has an internal cleanup thread which monitors and cleans up unclosed connections. This property sets the duration (in milliseconds) the cleanup thread will keep running if there is nothing to clean up. |

## Contributing
For information on how to contribute to the project see the [Contributing Guidelines](CONTRIBUTING.md)

----------------------------------------------------
### Sponsors

* [PostgreSQL International](http://www.postgresintl.com)