Commit 5b1e4b02 by Rizal Hermawan

feat (json schema) : implement json shema validator. Story #3

parent cfebf8e3
......@@ -3,22 +3,34 @@
#
# For more info see: https://dart.dev/go/dot-packages-deprecation
#
# Generated by pub on 2021-06-02 13:49:54.018368.
# Generated by pub on 2021-06-16 11:37:19.886806.
args:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/args-2.1.1/lib/
async:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/async-2.5.0/lib/
boolean_selector:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/
characters:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib/
charcode:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib/
clock:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib/
collection:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib/
crypto:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/crypto-3.0.1/lib/
cupertino_icons:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/cupertino_icons-1.0.2/lib/
fake_async:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib/
flutter:file:///D:/flutter/2.0.4-stable/packages/flutter/lib/
flutter_sequence_animation_null_safety:file:///D:/flutter/2.0.4-stable/.pub-cache/git/flutter_sequence_animation_null_safety-773d67311fed31fae22214b385265ae275854495/lib/
flutter_test:file:///D:/flutter/2.0.4-stable/packages/flutter_test/lib/
font_awesome_flutter:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/font_awesome_flutter-9.0.0/lib/
http:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/
http_parser:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/http_parser-4.0.0/lib/
intl:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/intl-0.17.0/lib/
json_class:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/json_class-2.0.0+1/lib/
json_schema2:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/json_schema2-2.0.0+2/lib/
llswidget:../llswidget/lib/
logging:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/logging-1.0.1/lib/
matcher:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib/
meta:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib/
path:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib/
pedantic:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/pedantic-1.11.0/lib/
quiver:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/quiver-3.0.1/lib/
rest_client:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/rest_client-2.0.1+2/lib/
sky_engine:file:///D:/flutter/2.0.4-stable/bin/cache/pkg/sky_engine/lib/
source_span:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0/lib/
stack_trace:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/
......@@ -27,5 +39,7 @@ string_scanner:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.or
term_glyph:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/
test_api:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19/lib/
typed_data:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib/
uri:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/uri-1.0.0/lib/
uuid:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/uuid-3.0.4/lib/
vector_math:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib/
widgetparser:lib/
import 'package:widgetparser/widgetparser.dart';
import 'package:widgetparser/src/utils.dart';
import 'package:widgetparser/src/json_schema.dart';
import 'package:flutter/widgets.dart';
class ContainerWidgetParser extends WidgetParser {
......@@ -27,7 +28,96 @@ class ContainerWidgetParser extends WidgetParser {
decoration: map.containsKey('decoration') ? parseBoxDecoration(map['decoration']) : null,
);
return containerWidget;
const containerSchema = '''
{
"\$schema\": $schemaUrl,
"\$ref\": "${refSchema}Container",
"definitions": {
"Container": {
"type": "object",
"additionalProperties": false,
"properties": {
"widget": {
"type": "string"
},
"alignment": ${WidgetSchema.alignment},
"padding": {
"type": "string"
},
"color": ${WidgetSchema.color},
"margin": {
"type": "string"
},
"width": {
"type": "number"
},
"height": {
"type": "number"
},
"constraints": {
"\$ref\": "${refSchema}Constraints"
},
"child": {
"\$ref\": "${refSchema}Child"
},
"decoration": {
"\$ref\": "${refSchema}Decoration"
}
},
"required": [
"widget"
],
"title": "Container"
},
"Child": ${WidgetSchema.child},
"Constraints": ${WidgetSchema.constraints},
"Decoration": ${WidgetSchema.decoration},
"BorderRadius": ${WidgetSchema.borderRadius},
"BoxShadow": ${WidgetSchema.boxShadow}
}
}
''';
//example JSON for rendering Container
// {
// "widget": "Container",
// "alignment": "center",
// "padding": "0,0,0,0",
// "color": "#fff",
// "margin": "5,5,5,5",
// "width": 200.4,
// "height": 200.4,
// "constraints": {
// "minWidth": 0,
// "maxWidth": 0,
// "minHeight": 0,
// "maxHeight": 0
// },
// "child": {
// "widget": "Container"
// },
// "decoration": {
// "borderRadius": {
// "borderRadiusMethod": "vertical",
// "radius": [1.4,1.4]
// },
// "color": "#fff",
// "boxShadow": [
// {
// "color": "lls_dark,withOpacity,0.40",
// "blurRadius": 1.4,
// "spreadRadius": 1.4
// }
// ]
// }
// }
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(containerSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator']);
} else {
return containerWidget;
}
}
@override
......@@ -35,4 +125,4 @@ class ContainerWidgetParser extends WidgetParser {
@override
Type get widgetType => Container;
}
}
\ No newline at end of file
const schemaUrl = "http://json-schema.org/draft-06/schema#";
const refSchema = "#/definitions/";
class WidgetSchema {
static const child = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"widget": {
"type": "string",
"description": "the widget in question is the widget class from the flutter component or the class from the llswidget component",
"minLength": 1,
}
},
"required": [
"widget"
],
"title": "Child"
}
''';
static const constraints = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"minWidth": {
"type": "number",
"minimum": 0
},
"maxWidth": {
"type": "number",
"minimum": 0
},
"minHeight": {
"type": "number",
"minimum": 0
},
"maxHeight": {
"type": "number",
"minimum": 0
}
},
"required": [],
"title": "Constraints"
}
''';
static const decoration = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"borderRadius": {
"\$ref\": "${refSchema}BorderRadius"
},
"color": $color,
"boxShadow": {
"type": "array",
"items": {
"\$ref\": "${refSchema}BoxShadow"
}
}
},
"required": [],
"title": "Decoration"
}
''';
static const boxShadow = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"color": $color,
"blurRadius": {
"type": "number"
},
"spreadRadius": {
"type": "number"
}
},
"required": [],
"title": "BoxShadow"
}
''';
static const borderRadius = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"borderRadiusMethod": {
"type": "string",
"enum": ["circular","vertical","horizontal","only"]
},
"radius": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "number"
}
}
},
"required": [
"radius"
],
"title": "BorderRadius"
}
''';
static const color = '''
{
"type": "string",
"minLength": 4
}
''';
static const alignment = '''
{
"type": "string",
"enum": ["topLeft","topCenter","topRight","centerLeft","center","centerRight","bottomLeft","bottomCenter","bottomRight"]
}
''';
}
\ No newline at end of file
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:json_schema2/json_schema2.dart';
import 'package:llswidget/llswidget.dart';
import 'package:widgetparser/widgetparser.dart';
import 'package:widgetparser/src/drop_cap_text.dart';
import 'package:flutter/widgets.dart';
Map<String, dynamic> jsonSchemaValidation(widgetSchema, widgetJson) {
JsonSchema schema = JsonSchema.createSchema(widgetSchema);
Validator validator = Validator(schema);
bool validates = validator.validate(widgetJson);
return {
'validates': validates,
'validator': validator
};
}
Widget jsonSchemaErrorWidget(Validator validator) {
return Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: validator.errors.map((err) => Text(
err,
style: TextStyle(fontSize: 16),
),
).toList()
),
)
),
);
}
TextAlign parseTextAlign(String? textAlignString) {
//left the system decide
TextAlign textAlign = TextAlign.start;
......@@ -1252,21 +1282,21 @@ NetworkImage parseNetworkImage(String? url, {double? scale}) {
return NetworkImage(url!, scale: scale!);
}
BorderRadius parseBorderRadius(Map<String, dynamic> map) {
BorderRadius? parseBorderRadius(Map<String, dynamic> map) {
String borderRadiusMethod = map['borderRadiusMethod'];
Map<String, dynamic> radiusMap = map['radiusMap'];
Map<String, dynamic> radius = map['radius'];
if (borderRadiusMethod == 'circular') {
return BorderRadius.circular(radiusMap['all_directions']);
return BorderRadius.circular(radius[0]);
} else if (borderRadiusMethod == 'vertical') {
return BorderRadius.vertical(top: radiusMap['top'], bottom: radiusMap['bottom']);
return BorderRadius.vertical(top: radius[0], bottom: radius[1]);
} else if (borderRadiusMethod == 'horizontal') {
return BorderRadius.horizontal(left: radiusMap['left'], right: radiusMap['right']);
} else {
return BorderRadius.horizontal(left: radius[0], right: radius[1]);
} else if (borderRadiusMethod == 'only') {
return BorderRadius.only(
topLeft: radiusMap['topLeft'],
topRight: radiusMap['topRight'],
bottomLeft: radiusMap['bottomLeft'],
bottomRight: radiusMap['bottomRight']
topLeft: radius[0],
topRight: radius[1],
bottomRight: radius[2],
bottomLeft: radius[3]
);
}
}
......
......@@ -4,6 +4,7 @@ library widgetparser;
// author Rizal Hermawan <rizal.hermawan@locatorlogic.com>
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
//exports flutter widget parser
......@@ -114,7 +115,10 @@ class WidgetParserBuilder {
static Widget? buildFromMap(Map<String, dynamic>? map, BuildContext buildContext, MethodListener? listener) {
initDefaultParsersIfNess();
late SnackBar snackBar;
if (map == null) {
snackBar = SnackBar(content: Text("please initialize the widget's object to the WidgetBuilderParser."));
ScaffoldMessenger.of(buildContext).showSnackBar(snackBar);
return null;
}
String? widgetName = map['widget'];
......@@ -123,13 +127,15 @@ class WidgetParserBuilder {
try {
return parser.parse(map, buildContext, listener);
} catch (e) {
print(e.toString());
snackBar = SnackBar(content: Text(e.toString()));
ScaffoldMessenger.of(buildContext).showSnackBar(snackBar);
return null;
}
} else {
print("please initialize the $widgetName widget to the WidgetBuilderParser.");
snackBar = SnackBar(content: Text("please initialize the $widgetName widget to the WidgetBuilderParser."));
ScaffoldMessenger.of(buildContext).showSnackBar(snackBar);
return null;
}
return null;
}
static List<Widget> buildWidgets(List<dynamic> values, BuildContext buildContext, MethodListener? listener) {
......
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
async:
dependency: transitive
description:
......@@ -43,6 +50,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
cupertino_icons:
dependency: "direct main"
description:
......@@ -62,6 +76,15 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_sequence_animation_null_safety:
dependency: transitive
description:
path: "."
ref: "773d67311fed31fae22214b385265ae275854495"
resolved-ref: "773d67311fed31fae22214b385265ae275854495"
url: "https://git.locatorlogic.com/hermawan/flutter_sequence_animation_null_safety"
source: git
version: "3.0.1"
flutter_test:
dependency: "direct dev"
description: flutter
......@@ -74,13 +97,55 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "9.0.0"
http:
dependency: transitive
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.3"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
json_class:
dependency: transitive
description:
name: json_class
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0+1"
json_schema2:
dependency: "direct main"
description:
name: json_schema2
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0+2"
llswidget:
dependency: "direct main"
description:
path: "../llswidget"
relative: true
source: path
version: "0.0.1"
version: "0.0.5"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
matcher:
dependency: transitive
description:
......@@ -102,6 +167,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.0"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
rest_client:
dependency: transitive
description:
name: rest_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1+2"
sky_engine:
dependency: transitive
description: flutter
......@@ -156,6 +242,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
uri:
dependency: transitive
description:
name: uri
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.4"
vector_math:
dependency: transitive
description:
......
......@@ -17,6 +17,7 @@ dependencies:
llswidget:
path: ../llswidget
cupertino_icons: ^1.0.2
json_schema2: ^2.0.0+2
dev_dependencies:
flutter_test:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment