Hi Brandon, If the JSON data follows the typical format of name : value pairs, then JSONToToken can be used to convert the data into a record in Kepler or Ptolemy.
I've attached a sample model. I created it in Ptolemy and tried it out in Kepler, it works OK! It doesn't pop up any output windows, but if you double-click on each "Test" actor, this will show the output produced. This example uses an energy data feed sample from the Berkeley sMAP campus energy monitoring service. The JSON starts out as a string containing a record with a "uuid' field (value: a string) and a "Readings" field (value: an array of arrays of doubles - here, an array of [timestamp, reading] pairs). For your model, you'll need to manually annotate the type on the output port of the JSONToToken actor. There are notes in the example. The Kepler actor options menu is a bit different than Ptolemy, try: Right click -> Configure Ports Curly braces {} indicate a record type and arrayType() indicates an array type. You are right - this is not a well documented feature! The only Ptolemy models that happen to use it involve the web server, which isn't needed if you're just receiving data. Plus a couple really basic test cases. Edward and Christopher - I added this example as a test case in the Ptolemy repository at: $PTII/ptolemy/actor/data/lib/conversions/json/test/auto/JSONEnergyExample.xml Best, Beth On Mon, Dec 15, 2014 at 9:44 PM, Christopher Brooks <c...@eecs.berkeley.edu> wrote: > > Hi Brandon, > > Backward type inference can help with these JSONToToken models, see > > http://chess.eecs.berkeley.edu/pubs/1035.html - a poster > > http://ptolemy.eecs.berkeley.edu/books/Systems/chapters/TheTypeSystem.pdf > > In Ptolemy II, to enable backward type conversion in Vergil, right click > on the canvas, select Customize, then Configure, then check the > enableBackwardTypeInference box. > > In Kepler, it might be necessary to do something different, see > http://lists.nceas.ucsb.edu/kepler/pipermail/kepler-users/2013-October/002542.html > > For the JSON actor and Backward Type Conversion, see Marten's poster at > http://chess.eecs.berkeley.edu/pubs/1035.html > > See also > http://sisyphus.eecs.berkeley.edu:8079/hudson/job/ptII/javadoc/ptolemy/actor/lib/conversions/json/JSONToToken.html > and > http://sisyphus.eecs.berkeley.edu:8079/hudson/job/ptII/javadoc/ptolemy/actor/lib/conversions/json/TokenToJSON.html > though there is not much there. > > Martin's tech report "Maximally Permissive Composition of Actors in > Ptolemy II" at > http://www.eecs.berkeley.edu/Pubs/TechRpts/2013/EECS-2013-19.html also > has some info about JSONToToken. > > > > In a multicontributor environment, I suggest the following: > > - Where you can, use actor oriented classes to define models. This means > that people can "own" blocks of functionality and others can instantiate > them. If the original definition changes, then the users will see those > changes. > > - A nightly build with a test suite goes a long way to helping find > problems early. There is a Test actor that can be used in models to create > regression tests. $PTII/doc/coding/testing.htm has details. > > - In your version control system, always work at the head, branching can > consume resources when doing a merge. > > _Christopher > > > On 12/10/14 7:58 PM, Edward A. Lee wrote: > > > In the underlying Ptolemy system, we have a JavaScript actor that would be > ideal for this... > Not sure whether this is exposed in the Kepler libraries... > > Edward > > On 12/10/14, 2:16 PM, Brandon Kuczenski wrote: > > Hi all, > > I'm new to Kepler and I'm trying to build a minimal demo to show my > research group how the tool works. I have two questions, and the first > is a two-parter. > > 1a- My first application is to pull down data from a web service (using > RESTService) and display it. In the WebService demo (Getting Started > 06) I see the XMLDisassembler actor is used. However, my data come back > in JSON format- It does not appear that there is a JSON analog for > XMLDisassembler. Any recommendations on how I could parse the data? > > 1b- One thing I tried was JSONToToken, thinking that a token was > something that might be more easily manipulated; it did not turn out to > be. In fact, I can't really find anything that I can connect to the > output of a JSONToToken actor. Is there a way for me to find actorsI > with input ports that are valid terminals for a given output port, or > vice-versa? > > 2- The team I'm working with includes about 14 people across several > academic departments. Are there any documents or helpful resources that > give practical advice on working with Kepler in a multi-contributor > environment? None of us has used the tool before. > > BTW it seems some actors (RESTService and JSON-anything, for instance) > are missing from the Actor Reference. > > Thanks in advance, > Brandon > > > > _______________________________________________ > Kepler-users mailing list > Kepler-users@kepler-project.org > http://lists.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-users > > > > -- > Christopher Brooks, PMP University of California > Academic Program Manager & Software Engineer US Mail: 337 Cory Hall > CHESS/iCyPhy/Ptolemy/TerraSwarm Berkeley, CA > 94720-1774...@eecs.berkeley.edu, 707.332.0670 (Office: 545Q Cory) > > > _______________________________________________ > Kepler-users mailing list > Kepler-users@kepler-project.org > http://lists.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-users > >
<?xml version="1.0" standalone="no"?> <!DOCTYPE entity PUBLIC "-//UC Berkeley//DTD MoML 1//EN" "http://ptolemy.eecs.berkeley.edu/xml/dtd/MoML_1.dtd"> <entity name="JSONEnergyExample" class="ptolemy.actor.TypedCompositeActor"> <property name="_createdBy" class="ptolemy.kernel.attributes.VersionAttribute" value="11.0.devel"> </property> <property name="_windowProperties" class="ptolemy.actor.gui.WindowPropertiesAttribute" value="{bounds={108, 0, 1224, 728}, maximized=false}"> </property> <property name="_vergilSize" class="ptolemy.actor.gui.SizeAttribute" value="[996, 611]"> </property> <property name="_vergilZoomFactor" class="ptolemy.data.expr.ExpertParameter" value="1.0000000000000004"> </property> <property name="_vergilCenter" class="ptolemy.data.expr.ExpertParameter" value="{487.9999999999999, 295.5}"> </property> <property name="JSONString" class="ptolemy.data.expr.Parameter" value=""{\"uuid\": \"b78a4d64-ed22-59d6-a331-b22704008749\", \"Readings\": [ [1338491730000.0, 692.0], [1338491881000.0, 705.0], [1338492031000.0, 703.0]]}""> <property name="_hideName" class="ptolemy.kernel.util.SingletonAttribute"> </property> <property name="_icon" class="ptolemy.vergil.icon.ValueIcon"> <property name="_color" class="ptolemy.actor.gui.ColorAttribute" value="{0.0, 0.0, 1.0, 1.0}"> </property> </property> <property name="_smallIconDescription" class="ptolemy.kernel.util.SingletonConfigurableAttribute"> <configure> <svg> <text x="20" style="font-size:14; font-family:SansSerif; fill:blue" y="20">-P-</text> </svg> </configure> </property> <property name="_editorFactory" class="ptolemy.vergil.toolbox.VisibleParameterEditorFactory"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[170.0, 30.0]"> </property> </property> <property name="SDF Director" class="ptolemy.domains.sdf.kernel.SDFDirector"> <property name="iterations" class="ptolemy.data.expr.Parameter" value="AUTO"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[65.0, 30.0]"> </property> </property> <property name="Annotation2" class="ptolemy.vergil.kernel.attributes.TextAttribute"> <property name="italic" class="ptolemy.data.expr.Parameter" value="false"> </property> <property name="text" class="ptolemy.kernel.util.StringAttribute" value="To add an output port to a RecordDisassembler, Right click -> Customize -> Ports Type in the port names, check "output" and click "Add" Port names are case-sensitive"> </property> <property name="_location" class="ptolemy.kernel.util.RelativeLocation" value="[-230.0, -95.0]"> <property name="relativeTo" class="ptolemy.kernel.util.StringAttribute" value="RecordDisassembler"> </property> <property name="relativeToElementName" class="ptolemy.kernel.util.StringAttribute" value="entity"> </property> </property> </property> <property name="enableBackwardTypeInference" class="ptolemy.data.expr.Parameter" value="true"> </property> <property name="Annotation3" class="ptolemy.vergil.kernel.attributes.TextAttribute"> <property name="italic" class="ptolemy.data.expr.Parameter" value="false"> </property> <property name="text" class="ptolemy.kernel.util.StringAttribute" value="Try a string function to make sure type resolves to a string "> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[660.0, 200.0]"> </property> </property> <property name="Annotation4" class="ptolemy.vergil.kernel.attributes.TextAttribute"> <property name="italic" class="ptolemy.data.expr.Parameter" value="false"> </property> <property name="text" class="ptolemy.kernel.util.StringAttribute" value="Try actors that require arrays to make sure we have an array of arrays Create an array of only readings (no timestamps) and compute the average "> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[465.0, 440.0]"> </property> </property> <property name="Annotation5" class="ptolemy.vergil.kernel.attributes.TextAttribute"> <property name="italic" class="ptolemy.data.expr.Parameter" value="false"> </property> <property name="text" class="ptolemy.kernel.util.StringAttribute" value="Specify the type of JSONToToken output port Right click -> Customize -> Ports For the output port, in the "Type" field, enter the type A record type is common for JSON. This example is a record with a string "uuid" field and an array of an array of doubles field called "Readings". The type is then: {uuid = string, Readings = arrayType(arrayType(double))} where the curly braces {} indicate a record. You might also have an array of such records; for example, arrayType({uuid = string, Readings = arrayType(arrayType(double))}) "> </property> <property name="_location" class="ptolemy.kernel.util.RelativeLocation" value="[-210.0, 35.0]"> <property name="relativeTo" class="ptolemy.kernel.util.StringAttribute" value="JSONToToken"> </property> <property name="relativeToElementName" class="ptolemy.kernel.util.StringAttribute" value="entity"> </property> </property> </property> <property name="Annotation6" class="ptolemy.vergil.kernel.attributes.TextAttribute"> <property name="italic" class="ptolemy.data.expr.Parameter" value="false"> </property> <property name="text" class="ptolemy.kernel.util.StringAttribute" value="This test case illustrates how to set the type of the output of a JSON to token actor. The JSON data is a Berkeley sMAP energy feed sample. It is a record containing the id of the energy feed, called "uuid", and an array of [timestamp, reading] pairs called "Readings". There are three [timestamp, reading] pairs. "> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[25.0, 60.0]"> </property> </property> <entity name="JSONToToken" class="ptolemy.actor.lib.conversions.json.JSONToToken"> <property name="_location" class="ptolemy.kernel.util.Location" value="[235.0, 310.0]"> </property> <port name="output" class="ptolemy.actor.TypedIOPort"> <property name="output"/> <property name="_type" class="ptolemy.actor.TypeAttribute" value="{ uuid = string, Readings = arrayType(arrayType(double))}"> </property> </port> </entity> <entity name="Const" class="ptolemy.actor.lib.Const"> <property name="value" class="ptolemy.data.expr.Parameter" value="JSONString"> </property> <doc>Create a constant sequence.</doc> <property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon"> <property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value"> </property> <property name="displayWidth" class="ptolemy.data.expr.Parameter" value="60"> </property> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[100.0, 310.0]"> </property> </entity> <entity name="RecordDisassembler" class="ptolemy.actor.lib.RecordDisassembler"> <property name="_location" class="ptolemy.kernel.util.Location" value="[370.0, 290.0]"> </property> <port name="uuid" class="ptolemy.actor.TypedIOPort"> <property name="output"/> <property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true"> </property> </port> <port name="Readings" class="ptolemy.actor.TypedIOPort"> <property name="output"/> <property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true"> </property> </port> </entity> <entity name="Test" class="ptolemy.actor.lib.Test"> <property name="correctValues" class="ptolemy.data.expr.Parameter" value="{"b78a4d64-ed22-59d6-a331-b22704008749"}"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[595.0, 220.0]"> </property> </entity> <entity name="Test2" class="ptolemy.actor.lib.Test"> <property name="correctValues" class="ptolemy.data.expr.Parameter" value="{36}"> </property> <property name="trainingMode" class="ptolemy.actor.parameters.SharedParameter" value="false"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[720.0, 290.0]"> </property> </entity> <entity name="StringLength" class="ptolemy.actor.lib.string.StringLength"> <doc>Output the length of an input string</doc> <property name="_location" class="ptolemy.kernel.util.Location" value="[600.0, 290.0]"> </property> </entity> <entity name="Test3" class="ptolemy.actor.lib.Test"> <property name="correctValues" class="ptolemy.data.expr.Parameter" value="{{{{1.33849173E12, 692.0}, {1.338491881E12, 705.0}, {1.338492031E12, 703.0}}}}"> </property> <property name="trainingMode" class="ptolemy.actor.parameters.SharedParameter" value="false"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[695.0, 535.0]"> </property> </entity> <entity name="Test4" class="ptolemy.actor.lib.Test"> <property name="correctValues" class="ptolemy.data.expr.Parameter" value="{{{692.0, 705.0, 703.0}}}"> </property> <property name="trainingMode" class="ptolemy.actor.parameters.SharedParameter" value="false"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="{725.0, 355.0}"> </property> </entity> <entity name="Test5" class="ptolemy.actor.lib.Test"> <property name="correctValues" class="ptolemy.data.expr.Parameter" value="{700.0}"> </property> <property name="tolerance" class="ptolemy.data.expr.Parameter" value="6.979999999999997E-7"> </property> <property name="trainingMode" class="ptolemy.actor.parameters.SharedParameter" value="false"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[870.0, 420.0]"> </property> </entity> <entity name="IterateOverArray" class="ptolemy.actor.lib.hoc.IterateOverArray"> <doc>Iterate a contained actor over input arrays</doc> <property name="_icon" class="ptolemy.vergil.icon.CopyCatIcon"> </property> <property name="_configurer" class="ptolemy.actor.gui.InsideEntityEditorPaneFactory"> </property> <property name="_tableauFactory" class="ptolemy.actor.gui.LevelSkippingTableauFactory"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[550.0, 390.0]"> </property> <port name="Readings" class="ptolemy.actor.lib.hoc.IterateOverArray$IteratePort"> <property name="input"/> <property name="_showName" class="ptolemy.data.expr.SingletonParameter" value="true"> </property> </port> <port name="output" class="ptolemy.actor.lib.hoc.IterateOverArray$IteratePort"> <property name="output"/> </port> <entity name="IterateComposite" class="ptolemy.actor.lib.hoc.IterateOverArray$IterateComposite"> <property name="SDF Director" class="ptolemy.domains.sdf.kernel.SDFDirector"> <property name="iterations" class="ptolemy.data.expr.Parameter" value="AUTO"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[70.0, 70.0]"> </property> </property> <property name="annotation" class="ptolemy.kernel.util.Attribute"> <property name="_hideName" class="ptolemy.kernel.util.SingletonAttribute"> </property> <property name="_iconDescription" class="ptolemy.kernel.util.SingletonConfigurableAttribute"> <configure><svg><text x="20" y="20" style="font-size:14; font-family:SansSerif; fill:blue">Get the second element in the array (index 1), which is the sensor value. The first element is the timestamp.</text></svg></configure> </property> <property name="_smallIconDescription" class="ptolemy.kernel.util.SingletonConfigurableAttribute"> <configure> <svg> <text x="20" style="font-size:14; font-family:SansSerif; fill:blue" y="20">-A-</text> </svg> </configure> </property> <property name="_controllerFactory" class="ptolemy.vergil.basic.NodeControllerFactory"> </property> <property name="_editorFactory" class="ptolemy.vergil.toolbox.AnnotationEditorFactory"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[60.0, 105.0]"> </property> </property> <property name="annotation2" class="ptolemy.kernel.util.Attribute"> <property name="_hideName" class="ptolemy.kernel.util.SingletonAttribute"> </property> <property name="_iconDescription" class="ptolemy.kernel.util.SingletonConfigurableAttribute"> <configure><svg><text x="20" y="20" style="font-size:14; font-family:SansSerif; fill:blue">Output an array of only the readings (no timestamps)</text></svg></configure> </property> <property name="_smallIconDescription" class="ptolemy.kernel.util.SingletonConfigurableAttribute"> <configure> <svg> <text x="20" style="font-size:14; font-family:SansSerif; fill:blue" y="20">-A-</text> </svg> </configure> </property> <property name="_controllerFactory" class="ptolemy.vergil.basic.NodeControllerFactory"> </property> <property name="_editorFactory" class="ptolemy.vergil.toolbox.AnnotationEditorFactory"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[190.0, 265.0]"> </property> </property> <port name="Readings" class="ptolemy.actor.lib.hoc.IterateOverArray$IteratePort"> <property name="input"/> <property name="_location" class="ptolemy.kernel.util.Location" value="[30.0, 230.0]"> </property> </port> <port name="output" class="ptolemy.actor.lib.hoc.IterateOverArray$IteratePort"> <property name="output"/> <property name="_location" class="ptolemy.kernel.util.Location" value="[225.0, 240.0]"> </property> </port> <entity name="ArrayElement" class="ptolemy.actor.lib.ArrayElement"> <property name="index" class="ptolemy.actor.parameters.PortParameter" value="1"> </property> <property name="_location" class="ptolemy.kernel.util.Location" value="[135.0, 240.0]"> </property> </entity> <relation name="relation" class="ptolemy.actor.TypedIORelation"> </relation> <relation name="relation2" class="ptolemy.actor.TypedIORelation"> </relation> <link port="Readings" relation="relation"/> <link port="output" relation="relation2"/> <link port="ArrayElement.input" relation="relation"/> <link port="ArrayElement.output" relation="relation2"/> </entity> </entity> <entity name="ArrayAverage" class="ptolemy.actor.lib.ArrayAverage"> <property name="_location" class="ptolemy.kernel.util.Location" value="[750.0, 420.0]"> </property> </entity> <relation name="relation" class="ptolemy.actor.TypedIORelation"> </relation> <relation name="relation2" class="ptolemy.actor.TypedIORelation"> </relation> <relation name="relation5" class="ptolemy.actor.TypedIORelation"> </relation> <relation name="relation4" class="ptolemy.actor.TypedIORelation"> <vertex name="vertex1" value="{450.0, 295.0}"> </vertex> </relation> <relation name="relation3" class="ptolemy.actor.TypedIORelation"> <vertex name="vertex1" value="[450.0, 325.0]"> </vertex> </relation> <relation name="relation6" class="ptolemy.actor.TypedIORelation"> <vertex name="vertex1" value="[620.0, 390.0]"> </vertex> </relation> <relation name="relation7" class="ptolemy.actor.TypedIORelation"> </relation> <link port="JSONToToken.input" relation="relation"/> <link port="JSONToToken.output" relation="relation2"/> <link port="Const.output" relation="relation"/> <link port="RecordDisassembler.input" relation="relation2"/> <link port="RecordDisassembler.uuid" relation="relation4"/> <link port="RecordDisassembler.Readings" relation="relation3"/> <link port="Test.input" relation="relation4"/> <link port="Test2.input" relation="relation5"/> <link port="StringLength.input" relation="relation4"/> <link port="StringLength.output" relation="relation5"/> <link port="Test3.input" relation="relation3"/> <link port="Test4.input" relation="relation6"/> <link port="Test5.input" relation="relation7"/> <link port="IterateOverArray.Readings" relation="relation3"/> <link port="IterateOverArray.output" relation="relation6"/> <link port="ArrayAverage.input" relation="relation6"/> <link port="ArrayAverage.output" relation="relation7"/> </entity>
_______________________________________________ Kepler-users mailing list Kepler-users@kepler-project.org http://lists.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-users