B4J Library [B4X] BalConverter - Convert the layouts files to JSON (and vice versa)

BalConverter is a B4J app (desktop app) that converts between the designer layout files and JSON format.

This allows you to edit the layout with a text editor. Note that the format is not so simple as the layout files were not designed to be edited this way.

The converter app is simple. You choose a folder and it will convert all layout files from one format to another. The original files are not deleted.
It filters the files based on the extension (bal or bal.json).

SS-2014-06-01_17.03.59.png


The JSON format is made of three main elements:

SS-2014-06-01_17.08.40.png


The Data element is a tree of views. All the views properties are stored here.

The first view is the Activity view. The other views are stored under the :kids node (recursively). Note that the fields order is not important and is not consistent.

SS-2014-06-01_17.11.10.png


The Variants element is a list of the variants. You will probably won't need to edit this section.

The LayoutHeader element holds other information about the layout file. Note that all the views names are stored in this section under ControlsHeaders. This means that if you change the name of a view then you need to change it here and in the Data element.

The b4j project is attached.

It is recommended to backup your layout files before working with this tool.

Updates

v2.30 - Designer script is now decoded and encoded. This means that it can be modified in the json file.
- Layout recreated with the internal designer.
- FontAwesome / Material Icons usage is preserved.
 

Attachments

  • BalConverter.zip
    6.3 KB · Views: 817
Last edited:

warwound

Expert
Licensed User
I can not imagine how you did.

The JSON file is so intricate!

Have you used the Replace only or are you able to get "clean" hierarchical structures of layouts?

Without this, the conversion is useless.

My PHP script uses the PHP json_decode function to turn the json created by BalConverter into a PHP object.
I then manipulate the PHP object and use the json_encode function to convert the object back into a json file.
BalConverter then converts this json file back into a new layout file.

If you'd like to see the script i can upload it...

Martin.
 

LucaMs

Expert
Licensed User
Thanks, Martin.

I do not know JSON (after all, I hate xml in general).

I think I could integrate the functions of this project with those of the JsonTree and get the same result.

The point is that the two sources are complex, I'll have to study a lot to get what I have posted in #18.

Thanks again.
 

Mashiane

Expert
Licensed User
My PHP script uses the PHP json_decode function to turn the json created by BalConverter into a PHP object.
I then manipulate the PHP object and use the json_encode function to convert the object back into a json file.
BalConverter then converts this json file back into a new layout file.

If you'd like to see the script i can upload it...

Martin.
Hi Martin, can you upload your script, im very curious. thanks
 

warwound

Expert
Licensed User
Here's that PHP script.

  • SOURCE_PATH is a folder full of JSON files.
    Each JSON file is a b4a .bal file converted to JSON using BalConverter.
  • DEST_PATH is where the script will save each updated file from SOURCE_PATH.
  • $layout_file_blacklist is an array of JSON file names from SOURCE_PATH that should be ignored by the script.
    In this example no files are ignored.
  • $resource_value_blacklist is an array of string values which should not be updated.
    These string values are typically the text properties of views such as Labels.
    If a view displays text that is in this array then that text value is not updated.
    So the script doesn't try to update text values such as the empty string and non-ascii characters.
  • $view_name_blacklist is an array of views names that the script should not update.

The main part of the script is this part:

PHP:
foreach ($directory_iterator as $xml_file) {

	if ($xml_file->isFile()) {
		$json_file_filename = $xml_file->getFilename();

		if (in_array($json_file_filename, $layout_file_blacklist)) {
			echo "Ignoring blacklisted layout file: '$json_file_filename'<br>";
		} else {
			$json_string = file_get_contents(SOURCE_PATH . "/$json_file_filename");
			if ($json_string === false) {
				echo "Failed to open layout file: '$json_file_filename'<br>";
			} else {
				$layout_object = json_decode($json_string, false);
				if ($layout_object === null) {
					echo "Failed to decode json in layout file: '$json_file_filename'";
				} else {
					echo "Updating layout file: '<b>$json_file_filename</b>'<br>";
					localize_kids_object($layout_object->{'Data'}->{':kids'}, $layout_object);
					echo '<hr>';

					file_put_contents(DEST_PATH . "/$json_file_filename", json_encode($layout_object));
				}
			}
		}
	}
}

It gets a list of files in the source directory.
Converts each file into a PHP JSON object and passes the object to the localize_kids_object() function.
localize_kids_object() then looks at the type of b4a View that is to be updated and updates it accordingly.
Finally the updated PHP JSON object is saved to the destination directory.

All files in the destination directory can then be converted from JSON to .bal using BalConverter.

Martin.
 

Attachments

  • b4a_layout_updater.zip
    2 KB · Views: 271

DavideV

Active Member
Licensed User
Hi, i'm sharing B4A projects with other developers over there. We compare and merge our projects using winmerge but unfortunately it can't handle .bal files so json will be good.
I just found this tool but it crashes with some layouts (in particular with customviews) and it's ok with others. We are using B4A V7.80. Does this tool need an update ?
Also if the source is public i really don't know where to put my hands on...

Thanks in advance
Davide
 

Alessandro71

Active Member
Licensed User
any chance of having Designer reading and writing text files directly?
it would simplify diffs and merges between projects
 

DavideV

Active Member
Licensed User
Great work Erel, thanks.

A side note: if you rebuild the layout from the json then you need to reopen it in the designer before make use of it.
I've got a crash with the layout uploaded above that make use of FontAwesome fonts. The log says: b4xfontawesome.otf not found in asset dir,
solved by open, save and close the layout from the designer (no other changes).

Have a Great New Year :)
 

ilan

Expert
Licensed User
this is really awesome, i was looking for this for a long time. i have one question, please. i would like to get only part of the json file back.

for example this is a part of the file:

"0": {
"padding": {
"ValueType": 12
},
"parent": "fingerpnl1",
"drawable": {
"file": "fingerprint.png",
"csType": "Dbasic.Designer.Drawable.BitmapDrawable",
"gravity": 119,
"type": ".drawable.BitmapDrawable"
},
"visible": false,
"pressed": false,
"csType": "Dbasic.Designer.MetaImageView",
"vanchor": 0,
"type": ".ImageViewWrapper",
"enabled": true,
"variant0": {
"top": 10,
"left": 20,
"hanchor": 0,
"width": 100,
"vanchor": 0,
"height": 120
},
"javaType": ".ImageViewWrapper",
"top": 20,
"left": 40,
"hanchor": 0,
"name": "fingerp1",
"width": 200,
"eventName": "fingerp1",
"tag": "",
"height": 240
},

what i need is only this:

"variant0": {
"top": 10,
"left": 20,
"width": 100,
"height": 120
},
"name": "fingerp1",

so the name of the view, his position (left and top) and size (width height).
can i get only those 5 parameteres for all views in the bal file?

thanx
 

ilan

Expert
Licensed User
Parse the json string and extract whatever information you need. It should be simple.

i would like to have something that will work with any bal file and not only with one.
i will try to get the info from the props map and create my own JSON file.
if i will make it this tool can save me lots of hours of codding. i can create a tool that handles the resizing of my layout. something today i do manually.
 
Top