add json validation

Change-Id: I241fca15e124d48bd10dc0b371a2b89c044a8952
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/5140
Commit-Queue: Keyong Han <keyonghan@google.com>
Reviewed-by: Godofredo Contreras <godofredoc@google.com>
diff --git a/recipe_modules/json_util/__init__.py b/recipe_modules/json_util/__init__.py
new file mode 100644
index 0000000..a568030
--- /dev/null
+++ b/recipe_modules/json_util/__init__.py
@@ -0,0 +1,4 @@
+DEPS = [
+    'recipe_engine/file',
+    'recipe_engine/path',
+]
diff --git a/recipe_modules/json_util/api.py b/recipe_modules/json_util/api.py
new file mode 100644
index 0000000..f61b4df
--- /dev/null
+++ b/recipe_modules/json_util/api.py
@@ -0,0 +1,22 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from recipe_engine import recipe_api
+
+
+class JsonUtilApi(recipe_api.RecipeApi):
+  """Provides utilities to work with json."""
+
+  def validate_json(self, dev_path, repo):
+    """Validates json format for different repos.
+
+    Args:
+      dev_path(Path): The path to dev dir of different repos.
+      repo(str): The repo name.
+    """
+    try_json_file = dev_path.join('dev', 'try_builders.json')
+    self.m.file.read_json('validate try json format', try_json_file)
+    if repo == 'engine' or repo == 'flutter':
+      prod_json_file = dev_path.join('dev', 'prod_builders.json')
+      self.m.file.read_json('validate prod json format', prod_json_file)
diff --git a/recipe_modules/json_util/examples/validate_json.expected/basic.json b/recipe_modules/json_util/examples/validate_json.expected/basic.json
new file mode 100644
index 0000000..95b4869
--- /dev/null
+++ b/recipe_modules/json_util/examples/validate_json.expected/basic.json
@@ -0,0 +1,41 @@
+[
+  {
+    "cmd": [
+      "vpython",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "[CLEANUP]/dev/try_builders.json",
+      "/path/to/tmp/"
+    ],
+    "infra_step": true,
+    "name": "validate try json format",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@try_builders.json@\"\"@@@",
+      "@@@STEP_LOG_END@try_builders.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "vpython",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "[CLEANUP]/dev/prod_builders.json",
+      "/path/to/tmp/"
+    ],
+    "infra_step": true,
+    "name": "validate prod json format",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@prod_builders.json@\"\"@@@",
+      "@@@STEP_LOG_END@prod_builders.json@@@"
+    ]
+  },
+  {
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipe_modules/json_util/examples/validate_json.py b/recipe_modules/json_util/examples/validate_json.py
new file mode 100644
index 0000000..377e685
--- /dev/null
+++ b/recipe_modules/json_util/examples/validate_json.py
@@ -0,0 +1,16 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from recipe_engine.post_process import (Filter)
+
+DEPS = [
+  'json_util',
+  'recipe_engine/path',
+]
+
+def RunSteps(api):
+  api.json_util.validate_json(api.path['cleanup'], 'engine')
+
+def GenTests(api):
+  yield api.test('basic')