question

qiu xiaohong avatar image
1 Like"
qiu xiaohong asked Ben Wilson edited

How to read or write json data in Flexsim

eg:

{ "destination_addresses" : [ "San Francisco, CA, USA" ], "origin_addresses" : [ "Vancouver, BC, Canada" ], "rows" : [ { "elements" : [ { "distance" : { "text" : "1,530 km", "value" : 1529516 }, "duration" : { "text" : "14 hours 46 mins", "value" : 53135 }, "status" : "OK" } ] } ], "status" : "OK" }

How to read distance value? How to update duration text?

FlexSim 16.0.4
json data
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Ben Wilson avatar image
1 Like"
Ben Wilson answered Ben Wilson edited

Starting with version 21.0.0, FlexSim includes a native JSON FlexScript API.

https://docs.flexsim.com/en/Reference/CodingInFlexSim/FlexScriptAPIReference/Data/JSON.html

The other answers on this question can help for older versions of FlexSim, but today you should use FlexSim's built-in JSON API.

5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Phil BoBo avatar image
8 Likes"
Phil BoBo answered Ben Wilson commented

Attached is a sample model with a user command that parses json input into a FlexSim tree structure. You can then access the information with node(), get(), and gets().

This is the parseJSON() user command's code (understanding how it works is not necessary for using it, but it is included here in case someone wants to see it without opening the model):

string json = parstr(1);
treenode target = parnode(2);


// clear out the target node
clearcontents(target);


// parse the JSON into a tree structure under the target node
treenode currentNode = target;
string delimiters = "{}[]\":,";
int onValue = 0;
int newObject = 0;
int emptyArray = 0;
string value = "";
for (int index = 1; index <= stringlen(json); index++) {
	string character = stringcopy(json, index, 1);
	
	if (stringsearch(delimiters, character, 0) >= 0) {
		if (onValue) {
			if (stringsearch(value, "true", 0) >= 0) {
				nodeadddata(currentNode, DATATYPE_STRING);
				sets(currentNode, "true");
				emptyArray = 0;
			} else if (stringsearch(value, "false", 0) >= 0) {
				nodeadddata(currentNode, DATATYPE_STRING);
				sets(currentNode, "false");
				emptyArray = 0;
			} else if (stringsearch(value, "null", 0) >= 0) {
				emptyArray = 0;
			} else {
				if (stringtonum(value) != 0) {
					nodeadddata(currentNode, DATATYPE_NUMBER);
					set(currentNode, stringtonum(value));
					emptyArray = 0;
				} else if (stringsearch(value, "0", 0) >= 0) {
					nodeadddata(currentNode, DATATYPE_NUMBER);
					set(currentNode, 0);
					emptyArray = 0;
				}
			}
			value = "";
		}
		if (comparetext(character, "{")) {
			if (!onValue) {
				currentNode = nodeinsertinto(currentNode);
				nodeadddata(currentNode, DATATYPE_OBJECT);
			}
			newObject = 1;
			onValue = 0;
			emptyArray = 0;
		} else if (comparetext(character, "}")) {
			currentNode = up(currentNode);
		} else if (comparetext(character, "[")) {
			currentNode = nodeinsertinto(currentNode);
			emptyArray = 1;
		} else if (comparetext(character, "]")) {
			currentNode = up(currentNode);
			if (emptyArray) {
				clearcontents(currentNode);
				emptyArray = 0;
			}
		} else if (comparetext(character, "\"")) {
			int closingQuoteIndex = stringsearch(json, "\"", index);
			string text = stringcopy(json, index + 1, closingQuoteIndex - index);
			index = closingQuoteIndex + 1;
			if (onValue) {
				nodeadddata(currentNode, DATATYPE_STRING);
				sets(currentNode, text);
				emptyArray = 0;
			} else {
				if (newObject) {
					nodeadddata(currentNode, DATATYPE_OBJECT);
					currentNode = nodeinsertinto(currentNode);
					newObject = 0;
				}
				setname(currentNode, text);
				emptyArray = 0;
			}
		} else if (comparetext(character, ":")) {
			onValue = 1;
		} else if (comparetext(character, ",")) {
			currentNode = nodeinsertafter(currentNode);
			if (getdatatype(up(currentNode)) == DATATYPE_OBJECT) {
				onValue = 0;
			}
		}
	} else if (onValue) {
		value = concat(value, character);
	}
}

parsejson.png (105.1 KiB)
parsejson.fsm (113.6 KiB)
· 2
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

qiu xiaohong avatar image qiu xiaohong commented ·

Flexsim reads the json data from mysql , but dbgettablestr read text length less than 254, If the length of the json data more than 254, It can't be full read. So how to read json data length more than 254 from mysql?

0 Likes 0 ·
Ben Wilson avatar image Ben Wilson ♦♦ qiu xiaohong commented ·

This comment has been posted as a separate question, so those interested should check there for updates regarding this MySQL import inquiry.

0 Likes 0 ·
Ben Wilson avatar image
4 Likes"
Ben Wilson answered Phil BoBo edited

This answer was inspired by @phil.bobo's answer, but attempts to cover a few deficiencies - namely, more robust JSON parsing to handle double quotes in strings, empty objects and arrays, and perhaps a few other edge cases, a way to translate the tree back to a JSON formatted string, and for good measure I also added a getter/setter that allows you to use Javascript style syntax to set and query the JSON data saved in FlexSim's tree.

The attached model (created with FlexSim 16.1.2), has the following main user commands:

  • jsonToTree - translates a valid JSON string to FlexSim's tree
  • treeToJSON - translates a FlexSim tree into a JSON formatted string
  • jsonGetSet - a way to get/set JSON values saved in FlexSim's tree using a javascript style syntax (dot syntax and indexed arrays)

Each user command is well-documented with comments in the code.

In addition to the 3 main user commands, there are additional helper user commands that are used by the main ones, including:

  • formatJSON_num - helps format a number for efficient translation from tree to JSON text
  • formatJSON_str - used to translate strings between the tree and JSON formatted text by (un)escaping JSON reserved characters that may be used in the strings
  • trim - removes whitespace from start and end of a string

Please comment below with any questions, suggestions, or bug reports. I will update this answer with any needed fixes or improvements that may come to light as it is used by more people. Let's build on this to make it the go-to library of commands for FlexSim+JSON integration!

NOTE: I wish FlexSim had a Boolean node type, but at this time it does not. Without a Boolean treenode datatype, handling true and false (and null) values is a bit trickier. The commands I've created save true, false, and null JSON values as strings in the FlexSim tree, but with subnodes indicating they are actually JSON special values. Alternatively, I considered using different treenode datatypes to represent true, false, and null. For instance, DATATYPE_COUPLING could have signified true, DATATYPE_SIMPLE false, and DATATYPE_BUNDLE as null. That may have been cleaner in some ways, but it would have been harder for a stranger to see and understand what was going on in the tree representation of the JSON data, so I opted to just use DATATYPE_STRING with a subnode to indicate JSON values rather than normal strings.

CHANGELOG

  • 20160901 - fixed a bug with detecting quotes and backslashes in strings, updated samplejson.txt with some additional test cases

· 4
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Yue Y avatar image Yue Y commented ·

Can we use a general treenode instead of a label to hold json object?

0 Likes 0 ·
Phil BoBo avatar image Phil BoBo ♦♦ Yue Y commented ·

Yes.

1 Like 1 ·
Yue Y avatar image Yue Y Phil BoBo ♦♦ commented ·

thank you! How can we achieve this?

0 Likes 0 ·
Show more comments
Aditya Prakash avatar image
2 Likes"
Aditya Prakash answered

API data can be parsed using string functions in flexscript. Similarly you can concatenate strings to write data. Attached is a sample model, where HTML webpage is stored in "/Tools/result" and then parsed to read RGB values. Similarly you can parse json data.getrandominternetcolor.fsm


5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.