EvaluateJsonPath unable to return a scalar - json

I'm trying to extract a value from JSON to a flowfile-attribute. When I run the EvaluateJsonPath processor I get an error stating
"Unable to get a scalar value for expression $..fields.storyBoard.stringValue.
Input JSON looks like this:
{
"name" : "projects/fakedims-0000/databases/(default)/documents/device/0000",
"fields" : {
"reportKey" : {
"stringValue" : "abc123"
},
"dateOccured" : {
"timestampValue" : "2018-10-14T04:00:00Z"
},
"storyBoard" : {
"stringValue" : "https://path/to/media"
},
"new" : {
"integerValue" : "25"
},
"name" : {
"stringValue" : "device one"
},
"location" : {
"geoPointValue" : {
"latitude" : -78.413751,
"longitude" : 38.156487
}
}
},
"createTime" : "2018-10-19T00:02:26.209335Z",
"updateTime" : "2018-10-19T22:22:24.382136Z"
}
The JSONPath expression is $..fields.storyBoard.stringValue
What I think is happening is that the processor is returning ["https://path/to/media"] rather than just the string.
This is what I get if a evaluate to flowfile-content rather than an attribute. Why? What can I do to fix it?

Change the Return Type property value to json in EvaluateJsonPath processor, if you are extracting as flowfile-attribute
Return Type property description:
Indicates the desired return type of the JSON Path expressions.
Selecting 'auto-detect' will set the return type to 'json' for a
Destination of 'flowfile-content', and 'scalar' for a Destination of
'flowfile-attribute'.
As you are trying to extract nested key not the key on the root level(ex:name,createTime..), that's the reason why we need to configure the Return Type as Json not as scalar.
In Addition you can use FlattenJson processor(seperator '_') to flatten-out all nested json then use Return Type as auto detect in EvaluateJsonPath processor.
EvaluateJsonConfigs:
Output:
We are going to have attribute value without enclosing in an array

Related

In Elm, how to decode a JSON object inside nested JSON

I use Elm 0.19.1 with NoRedInk/elm-json-decode-pipeline/1.0.0
I have an Aircraft type which is
type alias Aircraft = {name:String}
For this, I have the following decoder:
aircraftDecoder : Json.Decode.Decoder Aircraft
aircraftDecoder =
Json.Decode.succeed Aircraft
|> Json.Decode.Pipeline.required "name" Json.Decode.string
Unfortunately, the decoder is complaining me telling: "BadBody "Problem with the given value: (...)"
This is because actually my area of interest if full of noise around it (from an HATEOAS api), like this:
{
"_embedded" : {
"aircrafts" : [ {
"name" : "AC01",
"_links" : {
"self" : {
"href" : "http://localhost:8080/aircrafts/1"
},
"aircraft" : {
"href" : "http://localhost:8080/aircrafts/1"
}
}
}, {
"name" : "AC01",
"_links" : {
"self" : {
"href" : "http://localhost:8080/aircrafts/2"
},
"aircraft" : {
"href" : "http://localhost:8080/aircrafts/2"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/aircrafts{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/profile/aircrafts"
}
},
"page" : {
"size" : 20,
"totalElements" : 4,
"totalPages" : 1,
"number" : 0
}
}
How can I change the code, and keep using the Pipeline, so that the decoder doesn't get lost by all this noise?
I heard something about using Json.Decode.at, but the documentation is not good enough to let me get the correct code.
As far as I can tell, the problem is that:
at this moment, your decoder might be well fit to decode a single Aircraft
however, your JSON has a list of Aircrafts
also, you decoder does not know where, in the JSON, it might find Aircrafts
And you know, for Elm Aircraft and List Aircraft are completely different beats (as they should be). Anyway, the solution would be a two-step thing:
Telling the decoder where, within the JSON structure, are the Aircrafts
Parse a List Aircraft instead of a single Aircraft
Following your code and importing at and list from Json.Decode, the code might look like that:
listAircraftDecoder : Json.Decode.Decoder List Aircraft
listAircraftDecoder =
at ["_embedded", "aircrafts"] (list aircraftDecoder)
This means we're now aiming at a list of Aircrafts and that this list is an array within the JSON. Starting at the JSON root, take the property "_embedded" and, inside it, the property "aircrafts". This is a array, and Elm's list knows how to deal with it.
Finally, we just need to tell Elm's list to pass each element of the JSON array to a specific decoder – your aircraftDecoder in our case.
Does that make sense?
The following should work:
aircraftNameDecoder : Json.Decode.Decoder String
aircraftNameDecoder =
Json.Decode.map (Maybe.withDefault "" << List.head) <|
Json.Decode.at [ "_embedded", "aircrafts" ] <|
Json.Decode.list (Json.Decode.field "name" Json.Decode.string)
aircraftDecoder : Json.Decode.Decoder Aircraft
aircraftDecoder =
Json.Decode.succeed Aircraft
|> Json.Decode.Pipeline.custom aircraftNameDecoder
And please see elm/json for more documentation on Json.Decode.at.

Angular Json Property Undefined

I'm getting a Json object which contains other json object as properties .
[
{
"prop": "\{"p" : "1\"}"
}
]
I'm parsing it this way :
this.Auth.process().subscribe((x: any[]) => {
console.log(JSON.parse(x[0].prop)); /// Works
console.log('res: ' + JSON.parse(x[0].prop).p); /// Undefined.
});
when i try to retreive the json property i get undefined as result .
JSON.parse(x[0].prop).p is undefined because value of x[0].prop is string and not a JSON.
You can parse x[0] first and then fetch the value of p from the derived object -
JSON.parse(x)[0].prop
Your JSON is invalid. Try removing the quotes like this example.
[
{
"prop": {"p" : "1"}
}
]

JSON.stringify - accessing data

So I have Json obj which I convert via JSON.stringfy and the result is:
{
"data" : [ {
"id" : 417206355511802,
"name" : "test01"
}, {
"id" : 421211003974634,
"name" : "test02"
}, {
"id" : 403713622404901,
"name" : "test03"
}]
}
How can I access each name value? I was trying:
var test = result[0].name;
alert(test);
You can't access anything from the result of stringify() - it produces a string, hence its name. Rather, it sounds like you started with a string and converted it to an object via JSON.parse().
If that's not the case, and you already have the object, you don't need to stringify if you want to access properties.
That out of the way, you're missing the data step.
myobj.data[0].name; //<-- where myobj is the variable holding the object
JSON.stringify will not help you.becouse it's give a string as output.you can directly access the object elements by
var arr = myObj.data;
arr.forEach(function(elem) {
console.log(elem.id);
console.log(elem.name);
});

Extracting complete JSON object from mongo db object

My fetched DBObject looks like following
{ "_id" : { "$oid" : "50c28ac1de86acf0bdfbeca0"} ,
"schedule" : { "startAt" : 1354926785198 , "endAt" : 1391155200000 , "repeatForever" : true , "interval" : 3600} , "destination" : "Storage-East"}
I want to extract JSON string sans "_id" so that I can deserialize it back to my Java object. If I use following I can remove the '_id' field and it is fine to get the Java object back from JSON String. Is there any other elegant way of doing this ?
dbObj.removeField("_id");
String jsonString = dbObj.toString();
// Now readValue from the json string
thanks.
Instead of removing the data afterwords, just use results projections. You simply remove the _id by using the result projections in a find statement:
//find all documents where destination equals Storage-East, but exclude _id from result set
db.inventory.find( { "destination": 'Storage-East' }, { _id:0 } )
You can find the documentation http://docs.mongodb.org/manual/core/read-operations/#result-projections.

Retrieving nested element from MongoCursor

I am querying a Mongo DB in Scala and looping through the returned elements, that look like this:
{ "_id" : "123:1350918540586068000:v" ,
"i" : {
"vendorStyle" : "coolStyle" ,
"createdAt" : 1350918540580 ,
"productId" : "product123" ,
"skuId" : "123"
}
}
My question is: how do I retrieve the value from skuId? I know you can use the notation parent.child in the 'find' method in Mongo, but that doesn't work when reading from the resulting DBObject
This is the code:
val elems = SkuStorage.collection.find(MongoDBObject("i.productId" -> productId))
elems.toSeq.map { element=>
readSkuById(element.get("i.skuId")) //breaks!
}
Do I need to go get("i") then parse the string into a JSON? Is there any better way of handling this?
You could try
element.expand[String]("i.skuId")
it returns Option[String]