Skip to content

Commit

Permalink
Merge pull request #83 from milosimpson/jsonUtil2
Browse files Browse the repository at this point in the history
Refactor of JsonUtils, bump dependencies, and update Github docs
  • Loading branch information
Milo Simpson committed Feb 14, 2014
2 parents 760c58f + 3e49bd5 commit 91ed659
Show file tree
Hide file tree
Showing 48 changed files with 2,982 additions and 209 deletions.
67 changes: 38 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ JSON to JSON transformation library written in Java where the "specification" fo
* [1 Overview](#Overview)
* [2 Documentation](#Documentation)
* [3 Shiftr Transform DSL](#Shiftr_Transform_DSL)
* [4 Getting Started](#Getting_Started)
* [5 Getting Transform Help](#Getting_Transform_Help)
* [6 Alternatives](#Alternatives)
* [7 Performance](#Performance)
* [8 CLI](#CLI)
* [9 Code Coverage](#Code_Coverage)
* [10 Release Notes](#Release_Notes)
* [4 Demo](#Demo)
* [5 Getting Started](#Getting_Started)
* [6 Getting Transform Help](#Getting_Transform_Help)
* [7 Alternatives](#Alternatives)
* [8 Performance](#Performance)
* [9 CLI](#CLI)
* [10 Code Coverage](#Code_Coverage)
* [11 Release Notes](#Release_Notes)

## <a name="Overview"></a> Overview

Expand Down Expand Up @@ -60,37 +61,35 @@ Running a Jolt transform means creating an instance of [Chainr](https://github.c
The JSON spec for Chainr looks like : [unit test](https://github.com/bazaarvoice/jolt/blob/master/jolt-core/src/test/resources/json/chainr/firstSample.json).

The Java side looks like :
```
Chainr chainr = new Chainr( ...getResourceAsStream( "/path/to/chainr/spec.json" ) );

Object input = elasticSearchHit.getSource(); // ElasticSearch already returns hydrated JSon
Chainr chainr = JsonUtils.classpathToList( "/path/to/chainr/spec.json" );

Object output = chainr.transform( input );
Object input = elasticSearchHit.getSource(); // ElasticSearch already returns hydrated JSon

return output;
```
Object output = chainr.transform( input );

return output;

### <a name="Shiftr_Transform_DSL"></a> Shiftr Transform DSL

The Shiftr transform generally does most of the "heavy lifting" in the transform chain.
To see the Shiftr DSL in action, please look at our unit tests ([shiftr tests](https://github.com/bazaarvoice/jolt/tree/master/jolt-core/src/test/resources/json/shiftr)) for nice bite sized transform examples, and read the Shiftr [docs](https://github.com/bazaarvoice/jolt/blob/master/jolt-core/src/main/java/com/bazaarvoice/jolt/Shiftr.java).

Our unit tests follow the pattern :
```
{
"input": {
// sample input
},
"spec": {
// transform spec
},
"expected": {
// what the output of the transform looks like

{
"input": {
// sample input
},

"spec": {
// transform spec
},

"expected": {
// what the output of the transform looks like
}
}
}
```

We read in "input", apply the "spec", and [Diffy](https://github.com/bazaarvoice/jolt/blob/master/json-utils/src/main/java/com/bazaarvoice/jolt/Diffy.java) it against the "expected".

Expand All @@ -99,9 +98,19 @@ To learn the Shiftr DSL, examine "input" and "output" json, get an understanding
For reference, [this](https://github.com/bazaarvoice/jolt/blob/master/jolt-core/src/test/resources/json/shiftr/firstSample.json) was the very first test we wrote.


## <a name="Demo"></a> Demo

There is a demo available at [jolt-demo.appspot.com](http://jolt-demo.appspot.com/).
You can paste in JSON input data and a Spec, and it will post the data to server and run the transform.

Note

* it is hosted on a free Google App Engine instance, so it may take a minute to spin up.
* it validates in input JSON and spec client side, but if there are any errors server side it just silently fails.

## <a name="Getting_Started"></a> Getting Started

Has it's [own doc](gettingStarted.md).
Getting started code wise has it's [own doc](gettingStarted.md).

## <a name="Getting_Transform_Help"></a> Getting Transform Help

Expand Down Expand Up @@ -158,4 +167,4 @@ Currently code coverage is at 89% line, and 81% branch.

## <a name="Release_Notes"></a> Release Notes

On the [Github Jolt Wiki](https://github.com/bazaarvoice/jolt/wiki/Release-Notes).
[Versions and Release Notes available here](https://github.com/bazaarvoice/jolt/releases).
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public boolean process( Namespace ns ) {
JsonUtils.toPrettyJsonString( result.expected ) + "\n" +
"Input #2 contained this:\n" +
JsonUtils.toPrettyJsonString( result.actual ), suppressOutput );
} catch ( IOException e ) {
} catch ( Exception e ) {
JoltCliUtilities.printToStandardOut( "Differences found, but diffy encountered an error while writing the result.", suppressOutput );
} finally {
return false;
Expand Down
4 changes: 2 additions & 2 deletions cli/src/main/java/com/bazaarvoice/jolt/JoltCliUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public static boolean printJsonObject( Object output, Boolean uglyPrint, boolean
} else {
printToStandardOut( JsonUtils.toPrettyJsonString( output ), suppressOutput );
}
} catch ( IOException e ) {
} catch ( Exception e ) {
printToStandardOut( "An error occured while attempting to print the output.", suppressOutput );
return false;
}
Expand All @@ -98,7 +98,7 @@ public static Object readJsonInput( File file, boolean suppressOutput ) {
if ( file == null ) {
try {
jsonObject = JsonUtils.jsonToMap( System.in );
} catch ( IOException e ) {
} catch ( Exception e ) {
if ( e instanceof JsonParseException ) {
printToStandardOut( "Standard input did not contain properly formatted JSON.", suppressOutput );
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public static Chainr fromFile( File chainrSpecFile, ChainrInstantiator chainrIns
try {
FileInputStream fileInputStream = new FileInputStream( chainrSpecFile );
chainrSpec = JsonUtils.jsonToObject( fileInputStream );
} catch ( IOException e ) {
} catch ( Exception e ) {
throw new RuntimeException( "Unable to load chainr spec file " + chainrSpecFile.getAbsolutePath() );
}
return getChainr( chainrInstantiator, chainrSpec );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void testGetChainrInstanceFromClassPath_success()
AssertJUnit.assertTrue( "ChainrFactory did not return an instance of Chainr.", result instanceof Chainr );
}

@Test( expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load json file.*" )
@Test( expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load JSON.*" )
public void testGetChainrInstanceFromClassPath_error()
throws Exception {
ChainrFactory.fromClassPath( CLASSPATH + MALFORMED_INPUT_FILENAME );
Expand All @@ -60,7 +60,7 @@ public void testGetChainrInstanceFromClassPathWithInstantiator_success()
AssertJUnit.assertTrue( "ChainrFactory did not return an instance of Chainr.", result instanceof Chainr );
}

@Test( expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load json file.*" )
@Test( expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load JSON.*" )
public void testGetChainrInstanceFromClassPathWithInstantiator_error()
throws Exception {
ChainrFactory.fromClassPath( CLASSPATH + MALFORMED_INPUT_FILENAME, new DefaultChainrInstantiator() );
Expand All @@ -73,7 +73,7 @@ public void testGetChainrInstanceFromFileSystem_success()
AssertJUnit.assertTrue( "ChainrFactory did not return an instance of Chainr.", result instanceof Chainr );
}

@Test( expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load json file.*" )
@Test( expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load JSON.*" )
public void testGetChainrInstanceFromFileSystem_error()
throws Exception {
ChainrFactory.fromFileSystem( fileSystemPath + MALFORMED_INPUT_FILENAME );
Expand All @@ -86,7 +86,7 @@ public void testGetChainrInstanceFromFileSystemWithInstantiator_success()
AssertJUnit.assertTrue( "ChainrFactory did not return an instance of Chainr.", result instanceof Chainr );
}

@Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load json file.*")
@Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "Unable to load JSON.*")
public void testGetChainrInstanceFromFileSystemWithInstantiator_error()
throws Exception {
ChainrFactory.fromFileSystem( fileSystemPath + MALFORMED_INPUT_FILENAME, new DefaultChainrInstantiator() );
Expand Down
127 changes: 65 additions & 62 deletions gettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Maven Dependency to Add to your pom file
</dependency>
```

Where `latest.jolt.version` looks like `0.0.5`, and can be found by looking at the [project's tags](https://github.com/bazaarvoice/jolt/tags).
Where `latest.jolt.version` looks like `0.0.11`, and can be found by looking at the [project's releases](https://github.com/bazaarvoice/jolt/releases).

The two maven artifacts are:

Expand All @@ -33,85 +33,88 @@ The two maven artifacts are:
3. Replace the input and spec file with your own

### JoltSample.java
```
import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.JsonUtils;

import java.io.IOException;
Available [here](https://github.com/bazaarvoice/jolt/tree/master/jolt-core/src/test/java/com/bazaarvoice/jolt/sample/JoltSample.java).

public class JoltSample {
package com.bazaarvoice.jolt.sample;

public static void main(String[] args) throws IOException {
import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.JsonUtils;

Object chainrSpecJSON = JsonUtils.jsonToObject( JoltSample.class.getResourceAsStream( "chainrSpec.json" ) );
Chainr chainr = new Chainr( chainrSpecJSON );
import java.io.IOException;
import java.util.List;

Object inputJSON = JsonUtils.jsonToObject( JoltSample.class.getResourceAsStream( "input.json" ) );
public class JoltSample {

Object transformedOutput = chainr.transform( inputJSON );
System.out.println( JsonUtils.toJsonString( transformedOutput ) );
}
}
```
public static void main(String[] args) throws IOException {

### input.json
```
{
"rating": {
"primary": {
"value": 3
},
"quality": {
"value": 3
List chainrSpecJSON = JsonUtils.classpathToList( "/json/sample/spec.json" );
Chainr chainr = Chainr.fromSpec( chainrSpecJSON );

Object inputJSON = JsonUtils.classpathToObject( "/json/sample/input.json" );

Object transformedOutput = chainr.transform( inputJSON );
System.out.println( JsonUtils.toJsonString( transformedOutput ) );
}
}
}
```

### chainrSpec.json
```
[
### /json/sample/input.json
Available [here](https://github.com/bazaarvoice/jolt/tree/master/jolt-core/src/test/resources/json/sample/input.json).

{
"operation": "shift",
"spec": {
"rating": {
"primary": {
"value": "Rating"
},
"*": {
"value": "SecondaryRatings.&1.Value",
"$": "SecondaryRatings.&.Id"
}
"rating": {
"primary": {
"values": 3
},
"quality": {
"values": 3
}
}
},
{
"operation": "default",
"spec": {
"Range" : 5,
"SecondaryRatings" : {
"*" : {
"Range" : 5
}

### /json/sample/spec.json
Available [here](https://github.com/bazaarvoice/jolt/tree/master/jolt-core/src/test/resources/json/sample/spec.json).

[
{
"operation": "shift",
"spec": {
"rating": {
"primary": {
"values": "Rating"
},
"*": {
"values": "SecondaryRatings.&1.Value",
"$": "SecondaryRatings.&.Id"
}
}
}
},
{
"operation": "default",
"spec": {
"Range" : 5,
"SecondaryRatings" : {
"*" : {
"Range" : 5
}
}
}
}
}
]
```
]

### Output

Minus the pretty formatting, looks like :
```
{
"Rating": 3,
"Range": 5,
"SecondaryRatings": {
"quality": {
"Id": "quality",
"Value": 3,
"Range": 5
With pretty formatting, looks like :

{
"Rating": 3,
"Range": 5,
"SecondaryRatings": {
"quality": {
"Id": "quality",
"Value": 3,
"Range": 5
}
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2014 Bazaarvoice, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bazaarvoice.jolt.sample;

import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.JsonUtils;

import java.io.IOException;
import java.util.List;

public class JoltSample {

public static void main(String[] args) throws IOException {

List chainrSpecJSON = JsonUtils.classpathToList( "/json/sample/spec.json" );
Chainr chainr = Chainr.fromSpec( chainrSpecJSON );

Object inputJSON = JsonUtils.classpathToObject( "/json/sample/input.json" );

Object transformedOutput = chainr.transform( inputJSON );
System.out.println( JsonUtils.toJsonString( transformedOutput ) );
}
}
10 changes: 10 additions & 0 deletions jolt-core/src/test/resources/json/sample/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"rating": {
"primary": {
"value": 3
},
"quality": {
"value": 3
}
}
}
Loading

0 comments on commit 91ed659

Please sign in to comment.