Home | History | Annotate | Download | only in json
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/json/json_value_converter.h"
      6 
      7 #include <memory>
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/json/json_reader.h"
     12 #include "base/strings/string_piece.h"
     13 #include "base/values.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace base {
     17 namespace {
     18 
     19 // Very simple messages.
     20 struct SimpleMessage {
     21   enum SimpleEnum {
     22     FOO, BAR,
     23   };
     24   int foo;
     25   std::string bar;
     26   bool baz;
     27   bool bstruct;
     28   SimpleEnum simple_enum;
     29   std::vector<std::unique_ptr<int>> ints;
     30   std::vector<std::unique_ptr<std::string>> string_values;
     31   SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}
     32 
     33   static bool ParseSimpleEnum(StringPiece value, SimpleEnum* field) {
     34     if (value == "foo") {
     35       *field = FOO;
     36       return true;
     37     } else if (value == "bar") {
     38       *field = BAR;
     39       return true;
     40     }
     41     return false;
     42   }
     43 
     44   static bool HasFieldPresent(const base::Value* value, bool* result) {
     45     *result = value != nullptr;
     46     return true;
     47   }
     48 
     49   static bool GetValueString(const base::Value* value, std::string* result) {
     50     const base::DictionaryValue* dict = nullptr;
     51     if (!value->GetAsDictionary(&dict))
     52       return false;
     53 
     54     if (!dict->GetString("val", result))
     55       return false;
     56 
     57     return true;
     58   }
     59 
     60   static void RegisterJSONConverter(
     61       base::JSONValueConverter<SimpleMessage>* converter) {
     62     converter->RegisterIntField("foo", &SimpleMessage::foo);
     63     converter->RegisterStringField("bar", &SimpleMessage::bar);
     64     converter->RegisterBoolField("baz", &SimpleMessage::baz);
     65     converter->RegisterCustomField<SimpleEnum>(
     66         "simple_enum", &SimpleMessage::simple_enum, &ParseSimpleEnum);
     67     converter->RegisterRepeatedInt("ints", &SimpleMessage::ints);
     68     converter->RegisterCustomValueField<bool>("bstruct",
     69                                               &SimpleMessage::bstruct,
     70                                               &HasFieldPresent);
     71     converter->RegisterRepeatedCustomValue<std::string>(
     72         "string_values",
     73         &SimpleMessage::string_values,
     74         &GetValueString);
     75   }
     76 };
     77 
     78 // For nested messages.
     79 struct NestedMessage {
     80   double foo;
     81   SimpleMessage child;
     82   std::vector<std::unique_ptr<SimpleMessage>> children;
     83 
     84   NestedMessage() : foo(0) {}
     85 
     86   static void RegisterJSONConverter(
     87       base::JSONValueConverter<NestedMessage>* converter) {
     88     converter->RegisterDoubleField("foo", &NestedMessage::foo);
     89     converter->RegisterNestedField("child", &NestedMessage::child);
     90     converter->RegisterRepeatedMessage("children", &NestedMessage::children);
     91   }
     92 };
     93 
     94 }  // namespace
     95 
     96 TEST(JSONValueConverterTest, ParseSimpleMessage) {
     97   const char normal_data[] =
     98       "{\n"
     99       "  \"foo\": 1,\n"
    100       "  \"bar\": \"bar\",\n"
    101       "  \"baz\": true,\n"
    102       "  \"bstruct\": {},\n"
    103       "  \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
    104       "  \"simple_enum\": \"foo\","
    105       "  \"ints\": [1, 2]"
    106       "}\n";
    107 
    108   std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
    109   SimpleMessage message;
    110   base::JSONValueConverter<SimpleMessage> converter;
    111   EXPECT_TRUE(converter.Convert(*value.get(), &message));
    112 
    113   EXPECT_EQ(1, message.foo);
    114   EXPECT_EQ("bar", message.bar);
    115   EXPECT_TRUE(message.baz);
    116   EXPECT_EQ(SimpleMessage::FOO, message.simple_enum);
    117   EXPECT_EQ(2, static_cast<int>(message.ints.size()));
    118   ASSERT_EQ(2U, message.string_values.size());
    119   EXPECT_EQ("value_1", *message.string_values[0]);
    120   EXPECT_EQ("value_2", *message.string_values[1]);
    121   EXPECT_EQ(1, *(message.ints[0]));
    122   EXPECT_EQ(2, *(message.ints[1]));
    123 }
    124 
    125 TEST(JSONValueConverterTest, ParseNestedMessage) {
    126   const char normal_data[] =
    127       "{\n"
    128       "  \"foo\": 1.0,\n"
    129       "  \"child\": {\n"
    130       "    \"foo\": 1,\n"
    131       "    \"bar\": \"bar\",\n"
    132       "    \"bstruct\": {},\n"
    133       "    \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
    134       "    \"baz\": true\n"
    135       "  },\n"
    136       "  \"children\": [{\n"
    137       "    \"foo\": 2,\n"
    138       "    \"bar\": \"foobar\",\n"
    139       "    \"bstruct\": \"\",\n"
    140       "    \"string_values\": [{\"val\": \"value_1\"}],"
    141       "    \"baz\": true\n"
    142       "  },\n"
    143       "  {\n"
    144       "    \"foo\": 3,\n"
    145       "    \"bar\": \"barbaz\",\n"
    146       "    \"baz\": false\n"
    147       "  }]\n"
    148       "}\n";
    149 
    150   std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
    151   NestedMessage message;
    152   base::JSONValueConverter<NestedMessage> converter;
    153   EXPECT_TRUE(converter.Convert(*value.get(), &message));
    154 
    155   EXPECT_EQ(1.0, message.foo);
    156   EXPECT_EQ(1, message.child.foo);
    157   EXPECT_EQ("bar", message.child.bar);
    158   EXPECT_TRUE(message.child.baz);
    159   EXPECT_TRUE(message.child.bstruct);
    160   ASSERT_EQ(2U, message.child.string_values.size());
    161   EXPECT_EQ("value_1", *message.child.string_values[0]);
    162   EXPECT_EQ("value_2", *message.child.string_values[1]);
    163 
    164   EXPECT_EQ(2, static_cast<int>(message.children.size()));
    165   const SimpleMessage* first_child = message.children[0].get();
    166   ASSERT_TRUE(first_child);
    167   EXPECT_EQ(2, first_child->foo);
    168   EXPECT_EQ("foobar", first_child->bar);
    169   EXPECT_TRUE(first_child->baz);
    170   EXPECT_TRUE(first_child->bstruct);
    171   ASSERT_EQ(1U, first_child->string_values.size());
    172   EXPECT_EQ("value_1", *first_child->string_values[0]);
    173 
    174   const SimpleMessage* second_child = message.children[1].get();
    175   ASSERT_TRUE(second_child);
    176   EXPECT_EQ(3, second_child->foo);
    177   EXPECT_EQ("barbaz", second_child->bar);
    178   EXPECT_FALSE(second_child->baz);
    179   EXPECT_FALSE(second_child->bstruct);
    180   EXPECT_EQ(0U, second_child->string_values.size());
    181 }
    182 
    183 TEST(JSONValueConverterTest, ParseFailures) {
    184   const char normal_data[] =
    185       "{\n"
    186       "  \"foo\": 1,\n"
    187       "  \"bar\": 2,\n" // "bar" is an integer here.
    188       "  \"baz\": true,\n"
    189       "  \"ints\": [1, 2]"
    190       "}\n";
    191 
    192   std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
    193   SimpleMessage message;
    194   base::JSONValueConverter<SimpleMessage> converter;
    195   EXPECT_FALSE(converter.Convert(*value.get(), &message));
    196   // Do not check the values below.  |message| may be modified during
    197   // Convert() even it fails.
    198 }
    199 
    200 TEST(JSONValueConverterTest, ParseWithMissingFields) {
    201   const char normal_data[] =
    202       "{\n"
    203       "  \"foo\": 1,\n"
    204       "  \"baz\": true,\n"
    205       "  \"ints\": [1, 2]"
    206       "}\n";
    207 
    208   std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
    209   SimpleMessage message;
    210   base::JSONValueConverter<SimpleMessage> converter;
    211   // Convert() still succeeds even if the input doesn't have "bar" field.
    212   EXPECT_TRUE(converter.Convert(*value.get(), &message));
    213 
    214   EXPECT_EQ(1, message.foo);
    215   EXPECT_TRUE(message.baz);
    216   EXPECT_EQ(2, static_cast<int>(message.ints.size()));
    217   EXPECT_EQ(1, *(message.ints[0]));
    218   EXPECT_EQ(2, *(message.ints[1]));
    219 }
    220 
    221 TEST(JSONValueConverterTest, EnumParserFails) {
    222   const char normal_data[] =
    223       "{\n"
    224       "  \"foo\": 1,\n"
    225       "  \"bar\": \"bar\",\n"
    226       "  \"baz\": true,\n"
    227       "  \"simple_enum\": \"baz\","
    228       "  \"ints\": [1, 2]"
    229       "}\n";
    230 
    231   std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
    232   SimpleMessage message;
    233   base::JSONValueConverter<SimpleMessage> converter;
    234   EXPECT_FALSE(converter.Convert(*value.get(), &message));
    235   // No check the values as mentioned above.
    236 }
    237 
    238 TEST(JSONValueConverterTest, RepeatedValueErrorInTheMiddle) {
    239   const char normal_data[] =
    240       "{\n"
    241       "  \"foo\": 1,\n"
    242       "  \"bar\": \"bar\",\n"
    243       "  \"baz\": true,\n"
    244       "  \"simple_enum\": \"baz\","
    245       "  \"ints\": [1, false]"
    246       "}\n";
    247 
    248   std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
    249   SimpleMessage message;
    250   base::JSONValueConverter<SimpleMessage> converter;
    251   EXPECT_FALSE(converter.Convert(*value.get(), &message));
    252   // No check the values as mentioned above.
    253 }
    254 
    255 }  // namespace base
    256