Repository: tefra/xsdata
Pull request #341 (2020-12-04 21:39:23)

JsonParser: Improve matching choice elements

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=341&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=341&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=341&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=341&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=341) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=341&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=341&metric=new_duplicated_lines_density&view=list)


codecov[bot]: # [Codecov](https://codecov.io/gh/tefra/xsdata/pull/341?src=pr&el=h1) Report
> Merging [#341](https://codecov.io/gh/tefra/xsdata/pull/341?src=pr&el=desc) (98a3b76) into [master](https://codecov.io/gh/tefra/xsdata/commit/badb31271d99a1f20eff11f00b45ef7634a83304?el=desc) (badb312) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/tefra/xsdata/pull/341/graphs/tree.svg?width=650&height=150&src=pr&token=YzDDLtywvl)](https://codecov.io/gh/tefra/xsdata/pull/341?src=pr&el=tree)

```diff
@@            Coverage Diff            @@
##            master      #341   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           70        70           
  Lines         5670      5672    +2     
  Branches       986       987    +1     
=========================================
+ Hits          5670      5672    +2     
```


| [Impacted Files](https://codecov.io/gh/tefra/xsdata/pull/341?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [xsdata/formats/dataclass/parsers/json.py](https://codecov.io/gh/tefra/xsdata/pull/341/diff?src=pr&el=tree#diff-eHNkYXRhL2Zvcm1hdHMvZGF0YWNsYXNzL3BhcnNlcnMvanNvbi5weQ==) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tefra/xsdata/pull/341?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/tefra/xsdata/pull/341?src=pr&el=footer). Last update [badb312...98a3b76](https://codecov.io/gh/tefra/xsdata/pull/341?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/xsdata/formats/dataclass/parsers/json.py b/xsdata/formats/dataclass/parsers/json.py
index 96934d50..9c5c2a69 100644
--- a/xsdata/formats/dataclass/parsers/json.py
+++ b/xsdata/formats/dataclass/parsers/json.py
@@ -121,16 +121,19 @@ class JsonParser(AbstractParser):
     def bind_choice_simple(self, value: Any, var: XmlVar) -> Any:
         """Bind data to one of the simple choice types and return the first
         that succeeds."""
-        orig_type = type(value)
+        choice = var.find_value_choice(value)
+        if choice:
+            return self.bind_value(choice, value)
+
+        # Sometimes exact type match doesn't work, eg Decimals, try all of them
+        is_list = isinstance(value, list)
         for choice in var.choices:
-            if choice.dataclass:
+            if choice.dataclass or choice.tokens != is_list:
                 continue
 
-            with warnings.catch_warnings():
-                warnings.simplefilter("ignore")
-
+            with warnings.catch_warnings(record=True) as w:
                 result = self.bind_value(choice, value)
-                if not isinstance(result, orig_type):
+                if not w:
                     return result
 
         return value


Test patch:
diff --git a/tests/formats/dataclass/parsers/test_json.py b/tests/formats/dataclass/parsers/test_json.py
index 48b2abdb..05cd5396 100644
--- a/tests/formats/dataclass/parsers/test_json.py
+++ b/tests/formats/dataclass/parsers/test_json.py
@@ -96,11 +96,14 @@ class JsonParserTests(TestCase):
             name="compound",
             choices=[
                 XmlElement(qname="int", name="int", types=[int]),
+                XmlElement(qname="tokens", name="tokens", types=[int], tokens=True),
                 XmlElement(qname="generic", name="generic", dataclass=True),
                 XmlElement(qname="float", name="float", types=[float]),
             ],
         )
         self.assertEqual(1.0, self.parser.bind_choice("1.0", var))
+        self.assertEqual(1, self.parser.bind_choice(1, var))
+        self.assertEqual([1], self.parser.bind_choice(["1"], var))
         self.assertEqual("a", self.parser.bind_choice("a", var))
 
     def test_bind_choice_dataclass(self):