Class Defaultr

java.lang.Object
com.bazaarvoice.jolt.Defaultr
All Implemented Interfaces:
JoltTransform, SpecDriven, Transform

public class Defaultr extends Object implements SpecDriven, Transform
Defaultr is a kind of JOLT transform that applies default values in a non-destructive way. For comparison : Shitr walks the input data and asks its spec "Where should this go?" Defaultr walks the spec and asks "Does this exist in the data? If not, add it." Example : Given input JSON like
 {
   "Rating":3,
   "SecondaryRatings":{
      "quality":{
         "Range":7,
         "Value":3,
         "Id":"quality"
      },
      "sharpness": {
         "Value":4,
         "Id":"sharpness"
      }
   }
 }
 
With the desired output being :
 {
   "Rating":3,
   "RatingRange" : 5,
   "SecondaryRatings":{
      "quality":{
         "Range":7,
         "Value":3,
         "Id":"quality",
         "ValueLabel": null,
         "Label": null,
         "MaxLabel": "Great",
         "MinLabel": "Terrible",
         "DisplayType": "NORMAL"
      },
      "sharpness": {
         "Range":5,
         "Value":4,
         "Id":"sharpness",
         "ValueLabel": null,
         "Label": null,
         "MaxLabel": "High",
         "MinLabel": "Low",
         "DisplayType": "NORMAL"
      }
   }
 }
 
This is what the Defaultr Spec would look like
 {
   "RatingRange" : 5,
   "SecondaryRatings": {
     "quality|value" : {
        "ValueLabel": null,
        "Label": null,
        "MaxLabel": "Great",
        "MinLabel": "Terrible",
        "DisplayType": "NORMAL"

     }
     "*": {
        "Range" : 5,
        "ValueLabel": null,
        "Label": null,
        "MaxLabel": "High",
        "MinLabel": "Low",
        "DisplayType": "NORMAL"
     }
   }
 }
 
The Spec file format for Defaulr a tree Mapinvalid input: '<'String, Object> objects. Defaultr handles outputting of JSON Arrays via special wildcard in the Spec. Defaltr Spec WildCards and Flag : "*" aka STAR : Apply these defaults to all input keys at this level "|" aka OR : Apply these defaults to input keys, if they exist "[]" aka : Signal to Defaultr that the data for this key should be an array. This means all defaultr keys below this entry have to be "integers". Valid Array Specification :
 {
   "photos[]" : {
     "2" : {
       "url" : "http://www.bazaarvoice.com",
       "caption" : ""
     }
   }
 }
 
An Invalid Array Specification would be :
 {
   "photos[]" : {
     "photo-id-1234" : {
       "url" : "http://www.bazaarvoice.com",
       "caption" : ""
     }
   }
 }
 
Algorithm Defaultr walks its Spec in a depth first way. At each level in the Spec tree, Defaultr, works from most specific to least specific Spec key: Literals key values "|", sub-sorted by how many or values there, then alphabetically (for deterministic behavior) "*" At a given level in the Defaultr Spec tree, only literal keys force Defaultr to create new entries in the input data: either as a single literal value or adding new nested Array or Map objects. The wildcard operators, are applied after the literal keys, and will not cause the those keys to be added if they are not already present in the input document (either naturally or having been defaulted in from literal spec keys). Algorithm : 1) Walk the spec 2) for each literal key in the spec (specKey) 2.1) if the the specKey is a map or array, and the input is null, default an empty Map or Array into the output 2.2.1) re-curse on the literal spec 2.2) if the the specKey is a map or array, and the input is not null, but of the "wrong" type, skip and do not recurse 2.2) if the the specKey, is a literal value, default the literal and value into the output and do not recurse 3) for each wildcard in the spec 3.1) find all keys from the defaultee that match the wildcard 3.2) treat each key as a literal speckey Corner Cases : Due to Defaultr's array syntax, we can't actually express that we expect the top level of the input to be an Array. The workaround for this is that we check the type of the object that is at the root level of the input. If it is a map, no problem. If it is an array, we treat the "root" level of the Defaultr spec, as if it were the child of an Array type Defaultr entry. To force unambiguity, Defaultr throws an Exception if the input is null.
  • Field Details

    • mapRoot

      private final Key mapRoot
    • arrayRoot

      private final Key arrayRoot
  • Constructor Details

    • Defaultr

      @Inject public Defaultr(Object spec)
      Configure an instance of Defaultr with a spec.
      Throws:
      SpecException - for a malformed spec or if there are issues
  • Method Details

    • transform

      public Object transform(Object input)
      Top level standalone Defaultr method.
      Specified by:
      transform in interface Transform
      Parameters:
      input - JSON object to have defaults applied to. This will be modified.
      Returns:
      the modified input