Merge branch 'mike-json-support-module'

This commit is contained in:
Mike Hearn 2017-03-08 15:06:50 +01:00
commit ca70ca051c
11 changed files with 93 additions and 25 deletions

View File

@ -179,7 +179,7 @@ bintrayConfig {
projectUrl = 'https://github.com/corda/corda'
gpgSign = true
gpgPassphrase = System.getenv('CORDA_BINTRAY_GPG_PASSPHRASE')
publications = ['client', 'core', 'corda', 'corda-webserver', 'finance', 'node', 'node-schemas', 'test-utils']
publications = ['client', 'core', 'corda', 'corda-webserver', 'finance', 'node', 'node-schemas', 'test-utils', 'jackson']
license {
name = 'Apache-2.0'
url = 'https://www.apache.org/licenses/LICENSE-2.0'
@ -198,7 +198,7 @@ dokka {
moduleName = 'corda'
outputDirectory = 'docs/build/html/api/kotlin'
processConfigurations = ['compile']
sourceDirs = files('core/src/main/kotlin', 'client/src/main/kotlin', 'node/src/main/kotlin', 'finance/src/main/kotlin')
sourceDirs = files('core/src/main/kotlin', 'client/src/main/kotlin', 'node/src/main/kotlin', 'finance/src/main/kotlin', 'client/jackson/src/main/kotlin')
}
task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) {
@ -206,7 +206,7 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) {
outputFormat = "javadoc"
outputDirectory = 'docs/build/html/api/javadoc'
processConfigurations = ['compile']
sourceDirs = files('core/src/main/kotlin', 'client/src/main/kotlin', 'node/src/main/kotlin', 'finance/src/main/kotlin')
sourceDirs = files('core/src/main/kotlin', 'client/src/main/kotlin', 'node/src/main/kotlin', 'finance/src/main/kotlin', 'client/jackson/src/main/kotlin')
}
task apidocs(dependsOn: ['dokka', 'dokkaJavadoc'])

View File

@ -0,0 +1,19 @@
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'net.corda.plugins.publish-utils'
repositories {
mavenLocal()
mavenCentral()
jcenter()
maven {
url 'https://dl.bintray.com/kotlin/exposed'
}
}
dependencies {
compile project(':core')
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile ("com.fasterxml.jackson.module:jackson-module-kotlin:${jackson_version}")
testCompile "junit:junit:$junit_version"
}

View File

@ -1,4 +1,4 @@
package net.corda.webserver.utilities
package net.corda.jackson
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParseException
@ -13,10 +13,10 @@ import net.corda.core.contracts.BusinessCalendar
import net.corda.core.crypto.*
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.IdentityService
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.i2p.crypto.eddsa.EdDSAPublicKey
import net.corda.core.node.services.IdentityService
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime
@ -25,9 +25,11 @@ import java.time.LocalDateTime
* Utilities and serialisers for working with JSON representations of basic types. This adds Jackson support for
* the java.time API, some core types, and Kotlin data classes.
*
* TODO: This does not belong in node. It should be moved to the client module or a dedicated webserver module.
* Note that Jackson can also be used to serialise/deserialise other formats such as Yaml and XML.
*/
object JsonSupport {
object JacksonSupport {
// If you change this API please update the docs in the docsite (json.rst)
interface PartyObjectMapper {
fun partyFromName(partyName: String): Party?
fun partyFromKey(owningKey: CompositeKey): Party?
@ -84,13 +86,16 @@ object JsonSupport {
}
}
/* Mapper requiring RPC support to deserialise parties from names */
/** Mapper requiring RPC support to deserialise parties from names */
@JvmStatic
fun createDefaultMapper(rpc: CordaRPCOps): ObjectMapper = configureMapper(RpcObjectMapper(rpc))
/* For testing or situations where deserialising parties is not required */
/** For testing or situations where deserialising parties is not required */
@JvmStatic
fun createNonRpcMapper(): ObjectMapper = configureMapper(NoPartyObjectMapper())
/* For testing with an in memory identity service */
/** For testing with an in memory identity service */
@JvmStatic
fun createInMemoryMapper(identityService: IdentityService) = configureMapper(IdentityObjectMapper(identityService))
private fun configureMapper(mapper: ObjectMapper): ObjectMapper = mapper.apply {
@ -249,3 +254,4 @@ object JsonSupport {
}
}
}

View File

@ -1,20 +1,18 @@
package net.corda.webserver
package net.corda.jackson
import com.pholser.junit.quickcheck.From
import com.pholser.junit.quickcheck.Property
import com.pholser.junit.quickcheck.runner.JUnitQuickcheck
import net.corda.core.testing.PublicKeyGenerator
import net.corda.webserver.utilities.JsonSupport
import net.i2p.crypto.eddsa.EdDSAPublicKey
import org.junit.runner.RunWith
import java.security.PublicKey
import kotlin.test.assertEquals
@RunWith(JUnitQuickcheck::class)
class JsonSupportTest {
class JacksonSupportTest {
companion object {
val mapper = JsonSupport.createNonRpcMapper()
val mapper = JacksonSupport.createNonRpcMapper()
}
@Property

View File

@ -109,6 +109,7 @@ Documentation Contents:
network-simulator
clauses
merkle-trees
json
.. toctree::
:maxdepth: 2

42
docs/source/json.rst Normal file
View File

@ -0,0 +1,42 @@
.. highlight:: kotlin
.. raw:: html
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/codesets.js"></script>
JSON
====
Corda provides a module that extends the popular Jackson serialisation engine. Jackson is often used to serialise
to and from JSON, but also supports other formats such as YaML and XML. Jackson is itself very modular and has
a variety of plugins that extend its functionality. You can learn more at the `Jackson home page <https://github.com/FasterXML/jackson>`_.
To gain support for JSON serialisation of common Corda data types, include a dependency on ``net.corda:jackson:XXX``
in your Gradle or Maven build file, where XXX is of course the Corda version you are targeting (0.9 for M9, for instance).
Then you can obtain a Jackson ``ObjectMapper`` instance configured for use using the ``JacksonSupport.createNonRpcMapper()``
method. There are variants of this method for obtaining Jackson's configured in other ways: if you have an RPC
connection to the node (see ":doc:`clientrpc`") then your JSON mapper can resolve identities found in objects.
The API is described in detail here:
* `Kotlin API docs <api/kotlin/corda/net.corda.jackson/-jackson-support/index.html>`_
* `JavaDoc <api/javadoc/net/corda/jackson/package-summary.html>`_
.. container:: codeset
.. sourcecode:: kotlin
import net.corda.jackson.JacksonSupport
val mapper = JacksonSupport.createNonRpcMapper()
val json = mapper.writeValueAsString(myCordaState) // myCordaState can be any object.
.. sourcecode:: java
import net.corda.jackson.JacksonSupport
ObjectMapper mapper = JacksonSupport.createNonRpcMapper()
String json = mapper.writeValueAsString(myCordaState) // myCordaState can be any object.
.. note:: The way mappers interact with identity and RPC is likely to change in a future release.

View File

@ -44,6 +44,7 @@ sourceSets {
dependencies {
compile project(':core')
compile project(':node') // TODO: Break this dependency
compile project(':client:jackson')
// Web stuff: for HTTP[S] servlets
compile "org.eclipse.jetty:jetty-servlet:${jetty_version}"

View File

@ -2,7 +2,7 @@ package net.corda.webserver.servlets
import com.fasterxml.jackson.databind.ObjectMapper
import net.corda.core.messaging.CordaRPCOps
import net.corda.webserver.utilities.JsonSupport
import net.corda.jackson.JacksonSupport
import javax.ws.rs.ext.ContextResolver
import javax.ws.rs.ext.Provider
@ -12,6 +12,6 @@ import javax.ws.rs.ext.Provider
*/
@Provider
class ObjectMapperConfig(rpc: CordaRPCOps) : ContextResolver<ObjectMapper> {
val defaultObjectMapper = JsonSupport.createDefaultMapper(rpc)
val defaultObjectMapper = JacksonSupport.createDefaultMapper(rpc)
override fun getContext(type: Class<*>) = defaultObjectMapper
}

View File

@ -18,13 +18,11 @@ import net.corda.flows.TwoPartyDealFlow.Acceptor
import net.corda.flows.TwoPartyDealFlow.AutoOffer
import net.corda.flows.TwoPartyDealFlow.Instigator
import net.corda.irs.contract.InterestRateSwap
import net.corda.jackson.JacksonSupport
import net.corda.node.utilities.databaseTransaction
import net.corda.testing.initiateSingleShotFlow
import net.corda.testing.node.InMemoryMessagingNetwork
import net.corda.testing.node.MockIdentityService
import net.i2p.crypto.eddsa.KeyPairGenerator
import java.security.SecureRandom
import net.corda.webserver.utilities.JsonSupport
import java.time.LocalDate
import java.util.*
@ -33,7 +31,7 @@ import java.util.*
* A simulation in which banks execute interest rate swaps with each other, including the fixing events.
*/
class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork.LatencyCalculator?) : Simulation(networkSendManuallyPumped, runAsync, latencyInjector) {
val om = JsonSupport.createInMemoryMapper(MockIdentityService(network.identities))
val om = JacksonSupport.createInMemoryMapper(MockIdentityService(network.identities))
init {
currentDateAndTime = LocalDate.of(2016, 3, 8).atStartOfDay()

View File

@ -9,6 +9,7 @@ include 'node'
include 'node:capsule'
include 'node:webserver'
include 'client'
include 'client:jackson'
include 'experimental'
include 'experimental:sandbox'
include 'test-utils'
@ -22,4 +23,3 @@ include 'samples:network-visualiser'
include 'samples:simm-valuation-demo'
include 'samples:raft-notary-demo'
include 'samples:bank-of-corda-demo'

View File

@ -3,8 +3,11 @@ package net.corda.testing.http
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import net.corda.core.utilities.loggerFor
import net.corda.webserver.utilities.JsonSupport
import okhttp3.*
import net.corda.jackson.JacksonSupport
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import java.net.URL
import java.util.concurrent.TimeUnit
@ -19,7 +22,7 @@ object HttpUtils {
.readTimeout(60, TimeUnit.SECONDS).build()
}
val defaultMapper: ObjectMapper by lazy {
ObjectMapper().registerModule(JsonSupport.javaTimeModule).registerModule(KotlinModule())
ObjectMapper().registerModule(JacksonSupport.javaTimeModule).registerModule(KotlinModule())
}
fun putJson(url: URL, data: String) : Boolean {