"""Generated by atdpy from type definitions in semgrep_output_v1.atd.

This implements classes for the types defined in 'semgrep_output_v1.atd', providing
methods and functions to convert data from/to JSON.
"""

# Disable flake8 entirely on this file:
# flake8: noqa

# Import annotations to allow forward references
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, NoReturn, Optional, Tuple, Union

import json

############################################################################
# Private functions
############################################################################


def _atd_missing_json_field(type_name: str, json_field_name: str) -> NoReturn:
    raise ValueError(f"missing field '{json_field_name}'"
                     f" in JSON object of type '{type_name}'")


def _atd_bad_json(expected_type: str, json_value: Any) -> NoReturn:
    value_str = str(json_value)
    if len(value_str) > 200:
        value_str = value_str[:200] + '…'

    raise ValueError(f"incompatible JSON value where"
                     f" type '{expected_type}' was expected: '{value_str}'")


def _atd_bad_python(expected_type: str, json_value: Any) -> NoReturn:
    value_str = str(json_value)
    if len(value_str) > 200:
        value_str = value_str[:200] + '…'

    raise ValueError(f"incompatible Python value where"
                     f" type '{expected_type}' was expected: '{value_str}'")


def _atd_read_unit(x: Any) -> None:
    if x is None:
        return x
    else:
        _atd_bad_json('unit', x)


def _atd_read_bool(x: Any) -> bool:
    if isinstance(x, bool):
        return x
    else:
        _atd_bad_json('bool', x)


def _atd_read_int(x: Any) -> int:
    if isinstance(x, int):
        return x
    else:
        _atd_bad_json('int', x)


def _atd_read_float(x: Any) -> float:
    if isinstance(x, (int, float)):
        return x
    else:
        _atd_bad_json('float', x)


def _atd_read_string(x: Any) -> str:
    if isinstance(x, str):
        return x
    else:
        _atd_bad_json('str', x)


def _atd_read_list(
            read_elt: Callable[[Any], Any]
        ) -> Callable[[List[Any]], List[Any]]:
    def read_list(elts: List[Any]) -> List[Any]:
        if isinstance(elts, list):
            return [read_elt(elt) for elt in elts]
        else:
            _atd_bad_json('array', elts)
    return read_list


def _atd_read_assoc_array_into_dict(
            read_key: Callable[[Any], Any],
            read_value: Callable[[Any], Any],
        ) -> Callable[[List[Any]], Dict[Any, Any]]:
    def read_assoc(elts: List[List[Any]]) -> Dict[str, Any]:
        if isinstance(elts, list):
            return {read_key(elt[0]): read_value(elt[1]) for elt in elts}
        else:
            _atd_bad_json('array', elts)
            raise AssertionError('impossible')  # keep mypy happy
    return read_assoc


def _atd_read_assoc_object_into_dict(
            read_value: Callable[[Any], Any]
        ) -> Callable[[Dict[str, Any]], Dict[str, Any]]:
    def read_assoc(elts: Dict[str, Any]) -> Dict[str, Any]:
        if isinstance(elts, dict):
            return {_atd_read_string(k): read_value(v)
                    for k, v in elts.items()}
        else:
            _atd_bad_json('object', elts)
            raise AssertionError('impossible')  # keep mypy happy
    return read_assoc


def _atd_read_assoc_object_into_list(
            read_value: Callable[[Any], Any]
        ) -> Callable[[Dict[str, Any]], List[Tuple[str, Any]]]:
    def read_assoc(elts: Dict[str, Any]) -> List[Tuple[str, Any]]:
        if isinstance(elts, dict):
            return [(_atd_read_string(k), read_value(v))
                    for k, v in elts.items()]
        else:
            _atd_bad_json('object', elts)
            raise AssertionError('impossible')  # keep mypy happy
    return read_assoc


def _atd_read_nullable(read_elt: Callable[[Any], Any]) \
        -> Callable[[Optional[Any]], Optional[Any]]:
    def read_nullable(x: Any) -> Any:
        if x is None:
            return None
        else:
            return read_elt(x)
    return read_nullable


def _atd_read_option(read_elt: Callable[[Any], Any]) \
        -> Callable[[Optional[Any]], Optional[Any]]:
    def read_option(x: Any) -> Any:
        if x == 'None':
            return None
        elif isinstance(x, List) and len(x) == 2 and x[0] == 'Some':
            return read_elt(x[1])
        else:
            _atd_bad_json('option', x)
            raise AssertionError('impossible')  # keep mypy happy
    return read_option


def _atd_write_unit(x: Any) -> None:
    if x is None:
        return x
    else:
        _atd_bad_python('unit', x)


def _atd_write_bool(x: Any) -> bool:
    if isinstance(x, bool):
        return x
    else:
        _atd_bad_python('bool', x)


def _atd_write_int(x: Any) -> int:
    if isinstance(x, int):
        return x
    else:
        _atd_bad_python('int', x)


def _atd_write_float(x: Any) -> float:
    if isinstance(x, (int, float)):
        return x
    else:
        _atd_bad_python('float', x)


def _atd_write_string(x: Any) -> str:
    if isinstance(x, str):
        return x
    else:
        _atd_bad_python('str', x)


def _atd_write_list(
            write_elt: Callable[[Any], Any]
        ) -> Callable[[List[Any]], List[Any]]:
    def write_list(elts: List[Any]) -> List[Any]:
        if isinstance(elts, list):
            return [write_elt(elt) for elt in elts]
        else:
            _atd_bad_python('list', elts)
    return write_list


def _atd_write_assoc_dict_to_array(
            write_key: Callable[[Any], Any],
            write_value: Callable[[Any], Any]
        ) -> Callable[[Dict[Any, Any]], List[Tuple[Any, Any]]]:
    def write_assoc(elts: Dict[str, Any]) -> List[Tuple[str, Any]]:
        if isinstance(elts, dict):
            return [(write_key(k), write_value(v)) for k, v in elts.items()]
        else:
            _atd_bad_python('Dict[str, <value type>]]', elts)
            raise AssertionError('impossible')  # keep mypy happy
    return write_assoc


def _atd_write_assoc_dict_to_object(
            write_value: Callable[[Any], Any]
        ) -> Callable[[Dict[str, Any]], Dict[str, Any]]:
    def write_assoc(elts: Dict[str, Any]) -> Dict[str, Any]:
        if isinstance(elts, dict):
            return {_atd_write_string(k): write_value(v)
                    for k, v in elts.items()}
        else:
            _atd_bad_python('Dict[str, <value type>]', elts)
            raise AssertionError('impossible')  # keep mypy happy
    return write_assoc


def _atd_write_assoc_list_to_object(
            write_value: Callable[[Any], Any],
        ) -> Callable[[List[Any]], Dict[str, Any]]:
    def write_assoc(elts: List[List[Any]]) -> Dict[str, Any]:
        if isinstance(elts, list):
            return {_atd_write_string(elt[0]): write_value(elt[1])
                    for elt in elts}
        else:
            _atd_bad_python('List[Tuple[<key type>, <value type>]]', elts)
            raise AssertionError('impossible')  # keep mypy happy
    return write_assoc


def _atd_write_nullable(write_elt: Callable[[Any], Any]) \
        -> Callable[[Optional[Any]], Optional[Any]]:
    def write_nullable(x: Any) -> Any:
        if x is None:
            return None
        else:
            return write_elt(x)
    return write_nullable


def _atd_write_option(write_elt: Callable[[Any], Any]) \
        -> Callable[[Optional[Any]], Optional[Any]]:
    def write_option(x: Any) -> Any:
        if x is None:
            return 'None'
        else:
            return ['Some', write_elt(x)]
    return write_option


############################################################################
# Public classes
############################################################################


@dataclass(frozen=True)
class OSS:
    """Original type: engine_kind = [ ... | OSS | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'OSS'

    @staticmethod
    def to_json() -> Any:
        return 'OSS'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class PRO:
    """Original type: engine_kind = [ ... | PRO | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'PRO'

    @staticmethod
    def to_json() -> Any:
        return 'PRO'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class EngineKind:
    """Original type: engine_kind = [ ... ]"""

    value: Union[OSS, PRO]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'EngineKind':
        if isinstance(x, str):
            if x == 'OSS':
                return cls(OSS())
            if x == 'PRO':
                return cls(PRO())
            _atd_bad_json('EngineKind', x)
        _atd_bad_json('EngineKind', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'EngineKind':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class Fpath:
    """Original type: fpath"""

    value: str

    @classmethod
    def from_json(cls, x: Any) -> 'Fpath':
        return cls(_atd_read_string(x))

    def to_json(self) -> Any:
        return _atd_write_string(self.value)

    @classmethod
    def from_json_string(cls, x: str) -> 'Fpath':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class And:
    """Original type: matching_operation = [ ... | And | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'And'

    @staticmethod
    def to_json() -> Any:
        return 'And'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Or:
    """Original type: matching_operation = [ ... | Or | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Or'

    @staticmethod
    def to_json() -> Any:
        return 'Or'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Inside:
    """Original type: matching_operation = [ ... | Inside | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Inside'

    @staticmethod
    def to_json() -> Any:
        return 'Inside'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class XPat:
    """Original type: matching_operation = [ ... | XPat of ... | ... ]"""

    value: str

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'XPat'

    def to_json(self) -> Any:
        return ['XPat', _atd_write_string(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Negation:
    """Original type: matching_operation = [ ... | Negation | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Negation'

    @staticmethod
    def to_json() -> Any:
        return 'Negation'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Filter:
    """Original type: matching_operation = [ ... | Filter of ... | ... ]"""

    value: str

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Filter'

    def to_json(self) -> Any:
        return ['Filter', _atd_write_string(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Taint:
    """Original type: matching_operation = [ ... | Taint | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Taint'

    @staticmethod
    def to_json() -> Any:
        return 'Taint'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class TaintSource:
    """Original type: matching_operation = [ ... | TaintSource | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'TaintSource'

    @staticmethod
    def to_json() -> Any:
        return 'TaintSource'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class TaintSink:
    """Original type: matching_operation = [ ... | TaintSink | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'TaintSink'

    @staticmethod
    def to_json() -> Any:
        return 'TaintSink'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class TaintSanitizer:
    """Original type: matching_operation = [ ... | TaintSanitizer | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'TaintSanitizer'

    @staticmethod
    def to_json() -> Any:
        return 'TaintSanitizer'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class EllipsisAndStmts:
    """Original type: matching_operation = [ ... | EllipsisAndStmts | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'EllipsisAndStmts'

    @staticmethod
    def to_json() -> Any:
        return 'EllipsisAndStmts'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class ClassHeaderAndElems:
    """Original type: matching_operation = [ ... | ClassHeaderAndElems | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'ClassHeaderAndElems'

    @staticmethod
    def to_json() -> Any:
        return 'ClassHeaderAndElems'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class MatchingOperation:
    """Original type: matching_operation = [ ... ]"""

    value: Union[And, Or, Inside, XPat, Negation, Filter, Taint, TaintSource, TaintSink, TaintSanitizer, EllipsisAndStmts, ClassHeaderAndElems]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'MatchingOperation':
        if isinstance(x, str):
            if x == 'And':
                return cls(And())
            if x == 'Or':
                return cls(Or())
            if x == 'Inside':
                return cls(Inside())
            if x == 'Negation':
                return cls(Negation())
            if x == 'Taint':
                return cls(Taint())
            if x == 'TaintSource':
                return cls(TaintSource())
            if x == 'TaintSink':
                return cls(TaintSink())
            if x == 'TaintSanitizer':
                return cls(TaintSanitizer())
            if x == 'EllipsisAndStmts':
                return cls(EllipsisAndStmts())
            if x == 'ClassHeaderAndElems':
                return cls(ClassHeaderAndElems())
            _atd_bad_json('MatchingOperation', x)
        if isinstance(x, List) and len(x) == 2:
            cons = x[0]
            if cons == 'XPat':
                return cls(XPat(_atd_read_string(x[1])))
            if cons == 'Filter':
                return cls(Filter(_atd_read_string(x[1])))
            _atd_bad_json('MatchingOperation', x)
        _atd_bad_json('MatchingOperation', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'MatchingOperation':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class Position:
    """Original type: position = { ... }"""

    line: int
    col: int
    offset: int

    @classmethod
    def from_json(cls, x: Any) -> 'Position':
        if isinstance(x, dict):
            return cls(
                line=_atd_read_int(x['line']) if 'line' in x else _atd_missing_json_field('Position', 'line'),
                col=_atd_read_int(x['col']) if 'col' in x else _atd_missing_json_field('Position', 'col'),
                offset=_atd_read_int(x['offset']) if 'offset' in x else _atd_missing_json_field('Position', 'offset'),
            )
        else:
            _atd_bad_json('Position', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['line'] = _atd_write_int(self.line)
        res['col'] = _atd_write_int(self.col)
        res['offset'] = _atd_write_int(self.offset)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'Position':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Location:
    """Original type: location = { ... }"""

    path: Fpath
    start: Position
    end: Position

    @classmethod
    def from_json(cls, x: Any) -> 'Location':
        if isinstance(x, dict):
            return cls(
                path=Fpath.from_json(x['path']) if 'path' in x else _atd_missing_json_field('Location', 'path'),
                start=Position.from_json(x['start']) if 'start' in x else _atd_missing_json_field('Location', 'start'),
                end=Position.from_json(x['end']) if 'end' in x else _atd_missing_json_field('Location', 'end'),
            )
        else:
            _atd_bad_json('Location', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['path'] = (lambda x: x.to_json())(self.path)
        res['start'] = (lambda x: x.to_json())(self.start)
        res['end'] = (lambda x: x.to_json())(self.end)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'Location':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CliMatchIntermediateVar:
    """Original type: cli_match_intermediate_var = { ... }"""

    location: Location
    content: str

    @classmethod
    def from_json(cls, x: Any) -> 'CliMatchIntermediateVar':
        if isinstance(x, dict):
            return cls(
                location=Location.from_json(x['location']) if 'location' in x else _atd_missing_json_field('CliMatchIntermediateVar', 'location'),
                content=_atd_read_string(x['content']) if 'content' in x else _atd_missing_json_field('CliMatchIntermediateVar', 'content'),
            )
        else:
            _atd_bad_json('CliMatchIntermediateVar', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['location'] = (lambda x: x.to_json())(self.location)
        res['content'] = _atd_write_string(self.content)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliMatchIntermediateVar':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreMatchIntermediateVar:
    """Original type: core_match_intermediate_var = { ... }"""

    location: Location

    @classmethod
    def from_json(cls, x: Any) -> 'CoreMatchIntermediateVar':
        if isinstance(x, dict):
            return cls(
                location=Location.from_json(x['location']) if 'location' in x else _atd_missing_json_field('CoreMatchIntermediateVar', 'location'),
            )
        else:
            _atd_bad_json('CoreMatchIntermediateVar', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['location'] = (lambda x: x.to_json())(self.location)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreMatchIntermediateVar':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class RawJson:
    """Original type: raw_json"""

    value: Any

    @classmethod
    def from_json(cls, x: Any) -> 'RawJson':
        return cls((lambda x: x)(x))

    def to_json(self) -> Any:
        return (lambda x: x)(self.value)

    @classmethod
    def from_json_string(cls, x: str) -> 'RawJson':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class RuleId:
    """Original type: rule_id"""

    value: str

    @classmethod
    def from_json(cls, x: Any) -> 'RuleId':
        return cls(_atd_read_string(x))

    def to_json(self) -> Any:
        return _atd_write_string(self.value)

    @classmethod
    def from_json_string(cls, x: str) -> 'RuleId':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class SvalueValue:
    """Original type: svalue_value = { ... }"""

    svalue_abstract_content: str
    svalue_start: Optional[Position] = None
    svalue_end: Optional[Position] = None

    @classmethod
    def from_json(cls, x: Any) -> 'SvalueValue':
        if isinstance(x, dict):
            return cls(
                svalue_abstract_content=_atd_read_string(x['svalue_abstract_content']) if 'svalue_abstract_content' in x else _atd_missing_json_field('SvalueValue', 'svalue_abstract_content'),
                svalue_start=Position.from_json(x['svalue_start']) if 'svalue_start' in x else None,
                svalue_end=Position.from_json(x['svalue_end']) if 'svalue_end' in x else None,
            )
        else:
            _atd_bad_json('SvalueValue', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['svalue_abstract_content'] = _atd_write_string(self.svalue_abstract_content)
        if self.svalue_start is not None:
            res['svalue_start'] = (lambda x: x.to_json())(self.svalue_start)
        if self.svalue_end is not None:
            res['svalue_end'] = (lambda x: x.to_json())(self.svalue_end)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'SvalueValue':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class MetavarValue:
    """Original type: metavar_value = { ... }"""

    start: Position
    end: Position
    abstract_content: str
    propagated_value: Optional[SvalueValue] = None

    @classmethod
    def from_json(cls, x: Any) -> 'MetavarValue':
        if isinstance(x, dict):
            return cls(
                start=Position.from_json(x['start']) if 'start' in x else _atd_missing_json_field('MetavarValue', 'start'),
                end=Position.from_json(x['end']) if 'end' in x else _atd_missing_json_field('MetavarValue', 'end'),
                abstract_content=_atd_read_string(x['abstract_content']) if 'abstract_content' in x else _atd_missing_json_field('MetavarValue', 'abstract_content'),
                propagated_value=SvalueValue.from_json(x['propagated_value']) if 'propagated_value' in x else None,
            )
        else:
            _atd_bad_json('MetavarValue', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['start'] = (lambda x: x.to_json())(self.start)
        res['end'] = (lambda x: x.to_json())(self.end)
        res['abstract_content'] = _atd_write_string(self.abstract_content)
        if self.propagated_value is not None:
            res['propagated_value'] = (lambda x: x.to_json())(self.propagated_value)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'MetavarValue':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class Metavars:
    """Original type: metavars"""

    value: Dict[str, MetavarValue]

    @classmethod
    def from_json(cls, x: Any) -> 'Metavars':
        return cls(_atd_read_assoc_object_into_dict(MetavarValue.from_json)(x))

    def to_json(self) -> Any:
        return _atd_write_assoc_dict_to_object((lambda x: x.to_json()))(self.value)

    @classmethod
    def from_json_string(cls, x: str) -> 'Metavars':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class CoreLoc:
    """Original type: core_match_call_trace = [ ... | CoreLoc of ... | ... ]"""

    value: Location

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'CoreLoc'

    def to_json(self) -> Any:
        return ['CoreLoc', (lambda x: x.to_json())(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class CoreCall:
    """Original type: core_match_call_trace = [ ... | CoreCall of ... | ... ]"""

    value: Tuple[Location, List[CoreMatchIntermediateVar], CoreMatchCallTrace]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'CoreCall'

    def to_json(self) -> Any:
        return ['CoreCall', (lambda x: [(lambda x: x.to_json())(x[0]), _atd_write_list((lambda x: x.to_json()))(x[1]), (lambda x: x.to_json())(x[2])] if isinstance(x, tuple) and len(x) == 3 else _atd_bad_python('tuple of length 3', x))(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class CoreMatchCallTrace:
    """Original type: core_match_call_trace = [ ... ]"""

    value: Union[CoreLoc, CoreCall]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'CoreMatchCallTrace':
        if isinstance(x, List) and len(x) == 2:
            cons = x[0]
            if cons == 'CoreLoc':
                return cls(CoreLoc(Location.from_json(x[1])))
            if cons == 'CoreCall':
                return cls(CoreCall((lambda x: (Location.from_json(x[0]), _atd_read_list(CoreMatchIntermediateVar.from_json)(x[1]), CoreMatchCallTrace.from_json(x[2])) if isinstance(x, list) and len(x) == 3 else _atd_bad_json('array of length 3', x))(x[1])))
            _atd_bad_json('CoreMatchCallTrace', x)
        _atd_bad_json('CoreMatchCallTrace', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreMatchCallTrace':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreMatchDataflowTrace:
    """Original type: core_match_dataflow_trace = { ... }"""

    taint_source: Optional[CoreMatchCallTrace] = None
    intermediate_vars: Optional[List[CoreMatchIntermediateVar]] = None
    taint_sink: Optional[CoreMatchCallTrace] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CoreMatchDataflowTrace':
        if isinstance(x, dict):
            return cls(
                taint_source=CoreMatchCallTrace.from_json(x['taint_source']) if 'taint_source' in x else None,
                intermediate_vars=_atd_read_list(CoreMatchIntermediateVar.from_json)(x['intermediate_vars']) if 'intermediate_vars' in x else None,
                taint_sink=CoreMatchCallTrace.from_json(x['taint_sink']) if 'taint_sink' in x else None,
            )
        else:
            _atd_bad_json('CoreMatchDataflowTrace', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        if self.taint_source is not None:
            res['taint_source'] = (lambda x: x.to_json())(self.taint_source)
        if self.intermediate_vars is not None:
            res['intermediate_vars'] = _atd_write_list((lambda x: x.to_json()))(self.intermediate_vars)
        if self.taint_sink is not None:
            res['taint_sink'] = (lambda x: x.to_json())(self.taint_sink)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreMatchDataflowTrace':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreMatchExtra:
    """Original type: core_match_extra = { ... }"""

    metavars: Metavars
    engine_kind: EngineKind
    message: Optional[str] = None
    dataflow_trace: Optional[CoreMatchDataflowTrace] = None
    rendered_fix: Optional[str] = None
    extra_extra: Optional[RawJson] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CoreMatchExtra':
        if isinstance(x, dict):
            return cls(
                metavars=Metavars.from_json(x['metavars']) if 'metavars' in x else _atd_missing_json_field('CoreMatchExtra', 'metavars'),
                engine_kind=EngineKind.from_json(x['engine_kind']) if 'engine_kind' in x else _atd_missing_json_field('CoreMatchExtra', 'engine_kind'),
                message=_atd_read_string(x['message']) if 'message' in x else None,
                dataflow_trace=CoreMatchDataflowTrace.from_json(x['dataflow_trace']) if 'dataflow_trace' in x else None,
                rendered_fix=_atd_read_string(x['rendered_fix']) if 'rendered_fix' in x else None,
                extra_extra=RawJson.from_json(x['extra_extra']) if 'extra_extra' in x else None,
            )
        else:
            _atd_bad_json('CoreMatchExtra', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['metavars'] = (lambda x: x.to_json())(self.metavars)
        res['engine_kind'] = (lambda x: x.to_json())(self.engine_kind)
        if self.message is not None:
            res['message'] = _atd_write_string(self.message)
        if self.dataflow_trace is not None:
            res['dataflow_trace'] = (lambda x: x.to_json())(self.dataflow_trace)
        if self.rendered_fix is not None:
            res['rendered_fix'] = _atd_write_string(self.rendered_fix)
        if self.extra_extra is not None:
            res['extra_extra'] = (lambda x: x.to_json())(self.extra_extra)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreMatchExtra':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreMatch:
    """Original type: core_match = { ... }"""

    rule_id: RuleId
    location: Location
    extra: CoreMatchExtra

    @classmethod
    def from_json(cls, x: Any) -> 'CoreMatch':
        if isinstance(x, dict):
            return cls(
                rule_id=RuleId.from_json(x['rule_id']) if 'rule_id' in x else _atd_missing_json_field('CoreMatch', 'rule_id'),
                location=Location.from_json(x['location']) if 'location' in x else _atd_missing_json_field('CoreMatch', 'location'),
                extra=CoreMatchExtra.from_json(x['extra']) if 'extra' in x else _atd_missing_json_field('CoreMatch', 'extra'),
            )
        else:
            _atd_bad_json('CoreMatch', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['rule_id'] = (lambda x: x.to_json())(self.rule_id)
        res['location'] = (lambda x: x.to_json())(self.location)
        res['extra'] = (lambda x: x.to_json())(self.extra)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreMatch':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class MatchingExplanation:
    """Original type: matching_explanation = { ... }"""

    op: MatchingOperation
    children: List[MatchingExplanation]
    matches: List[CoreMatch]
    loc: Location

    @classmethod
    def from_json(cls, x: Any) -> 'MatchingExplanation':
        if isinstance(x, dict):
            return cls(
                op=MatchingOperation.from_json(x['op']) if 'op' in x else _atd_missing_json_field('MatchingExplanation', 'op'),
                children=_atd_read_list(MatchingExplanation.from_json)(x['children']) if 'children' in x else _atd_missing_json_field('MatchingExplanation', 'children'),
                matches=_atd_read_list(CoreMatch.from_json)(x['matches']) if 'matches' in x else _atd_missing_json_field('MatchingExplanation', 'matches'),
                loc=Location.from_json(x['loc']) if 'loc' in x else _atd_missing_json_field('MatchingExplanation', 'loc'),
            )
        else:
            _atd_bad_json('MatchingExplanation', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['op'] = (lambda x: x.to_json())(self.op)
        res['children'] = _atd_write_list((lambda x: x.to_json()))(self.children)
        res['matches'] = _atd_write_list((lambda x: x.to_json()))(self.matches)
        res['loc'] = (lambda x: x.to_json())(self.loc)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'MatchingExplanation':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class CliLoc:
    """Original type: cli_match_call_trace = [ ... | CliLoc of ... | ... ]"""

    value: Tuple[Location, str]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'CliLoc'

    def to_json(self) -> Any:
        return ['CliLoc', (lambda x: [(lambda x: x.to_json())(x[0]), _atd_write_string(x[1])] if isinstance(x, tuple) and len(x) == 2 else _atd_bad_python('tuple of length 2', x))(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class CliCall:
    """Original type: cli_match_call_trace = [ ... | CliCall of ... | ... ]"""

    value: Tuple[Tuple[Location, str], List[CliMatchIntermediateVar], CliMatchCallTrace]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'CliCall'

    def to_json(self) -> Any:
        return ['CliCall', (lambda x: [(lambda x: [(lambda x: x.to_json())(x[0]), _atd_write_string(x[1])] if isinstance(x, tuple) and len(x) == 2 else _atd_bad_python('tuple of length 2', x))(x[0]), _atd_write_list((lambda x: x.to_json()))(x[1]), (lambda x: x.to_json())(x[2])] if isinstance(x, tuple) and len(x) == 3 else _atd_bad_python('tuple of length 3', x))(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class CliMatchCallTrace:
    """Original type: cli_match_call_trace = [ ... ]"""

    value: Union[CliLoc, CliCall]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'CliMatchCallTrace':
        if isinstance(x, List) and len(x) == 2:
            cons = x[0]
            if cons == 'CliLoc':
                return cls(CliLoc((lambda x: (Location.from_json(x[0]), _atd_read_string(x[1])) if isinstance(x, list) and len(x) == 2 else _atd_bad_json('array of length 2', x))(x[1])))
            if cons == 'CliCall':
                return cls(CliCall((lambda x: ((lambda x: (Location.from_json(x[0]), _atd_read_string(x[1])) if isinstance(x, list) and len(x) == 2 else _atd_bad_json('array of length 2', x))(x[0]), _atd_read_list(CliMatchIntermediateVar.from_json)(x[1]), CliMatchCallTrace.from_json(x[2])) if isinstance(x, list) and len(x) == 3 else _atd_bad_json('array of length 3', x))(x[1])))
            _atd_bad_json('CliMatchCallTrace', x)
        _atd_bad_json('CliMatchCallTrace', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'CliMatchCallTrace':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class Version:
    """Original type: version"""

    value: str

    @classmethod
    def from_json(cls, x: Any) -> 'Version':
        return cls(_atd_read_string(x))

    def to_json(self) -> Any:
        return _atd_write_string(self.value)

    @classmethod
    def from_json_string(cls, x: str) -> 'Version':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Direct:
    """Original type: transitivity = [ ... | Direct | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Direct'

    @staticmethod
    def to_json() -> Any:
        return 'direct'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Transitive:
    """Original type: transitivity = [ ... | Transitive | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Transitive'

    @staticmethod
    def to_json() -> Any:
        return 'transitive'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Unknown:
    """Original type: transitivity = [ ... | Unknown | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Unknown'

    @staticmethod
    def to_json() -> Any:
        return 'unknown'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Transitivity:
    """Original type: transitivity = [ ... ]"""

    value: Union[Direct, Transitive, Unknown]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'Transitivity':
        if isinstance(x, str):
            if x == 'direct':
                return cls(Direct())
            if x == 'transitive':
                return cls(Transitive())
            if x == 'unknown':
                return cls(Unknown())
            _atd_bad_json('Transitivity', x)
        _atd_bad_json('Transitivity', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'Transitivity':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class RuleTimes:
    """Original type: rule_times = { ... }"""

    rule_id: RuleId
    parse_time: float
    match_time: float

    @classmethod
    def from_json(cls, x: Any) -> 'RuleTimes':
        if isinstance(x, dict):
            return cls(
                rule_id=RuleId.from_json(x['rule_id']) if 'rule_id' in x else _atd_missing_json_field('RuleTimes', 'rule_id'),
                parse_time=_atd_read_float(x['parse_time']) if 'parse_time' in x else _atd_missing_json_field('RuleTimes', 'parse_time'),
                match_time=_atd_read_float(x['match_time']) if 'match_time' in x else _atd_missing_json_field('RuleTimes', 'match_time'),
            )
        else:
            _atd_bad_json('RuleTimes', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['rule_id'] = (lambda x: x.to_json())(self.rule_id)
        res['parse_time'] = _atd_write_float(self.parse_time)
        res['match_time'] = _atd_write_float(self.match_time)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'RuleTimes':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class TargetTime:
    """Original type: target_time = { ... }"""

    path: Fpath
    rule_times: List[RuleTimes]
    run_time: float

    @classmethod
    def from_json(cls, x: Any) -> 'TargetTime':
        if isinstance(x, dict):
            return cls(
                path=Fpath.from_json(x['path']) if 'path' in x else _atd_missing_json_field('TargetTime', 'path'),
                rule_times=_atd_read_list(RuleTimes.from_json)(x['rule_times']) if 'rule_times' in x else _atd_missing_json_field('TargetTime', 'rule_times'),
                run_time=_atd_read_float(x['run_time']) if 'run_time' in x else _atd_missing_json_field('TargetTime', 'run_time'),
            )
        else:
            _atd_bad_json('TargetTime', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['path'] = (lambda x: x.to_json())(self.path)
        res['rule_times'] = _atd_write_list((lambda x: x.to_json()))(self.rule_times)
        res['run_time'] = _atd_write_float(self.run_time)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'TargetTime':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class GitignorePatternsMatch:
    """Original type: skip_reason = [ ... | Gitignore_patterns_match | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'GitignorePatternsMatch'

    @staticmethod
    def to_json() -> Any:
        return 'gitignore_patterns_match'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class AlwaysSkipped:
    """Original type: skip_reason = [ ... | Always_skipped | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'AlwaysSkipped'

    @staticmethod
    def to_json() -> Any:
        return 'always_skipped'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class SemgrepignorePatternsMatch:
    """Original type: skip_reason = [ ... | Semgrepignore_patterns_match | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'SemgrepignorePatternsMatch'

    @staticmethod
    def to_json() -> Any:
        return 'semgrepignore_patterns_match'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CliIncludeFlagsDoNotMatch:
    """Original type: skip_reason = [ ... | Cli_include_flags_do_not_match | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'CliIncludeFlagsDoNotMatch'

    @staticmethod
    def to_json() -> Any:
        return 'cli_include_flags_do_not_match'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CliExcludeFlagsMatch:
    """Original type: skip_reason = [ ... | Cli_exclude_flags_match | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'CliExcludeFlagsMatch'

    @staticmethod
    def to_json() -> Any:
        return 'cli_exclude_flags_match'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class ExceededSizeLimit:
    """Original type: skip_reason = [ ... | Exceeded_size_limit | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'ExceededSizeLimit'

    @staticmethod
    def to_json() -> Any:
        return 'exceeded_size_limit'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class AnalysisFailedParserOrInternalError:
    """Original type: skip_reason = [ ... | Analysis_failed_parser_or_internal_error | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'AnalysisFailedParserOrInternalError'

    @staticmethod
    def to_json() -> Any:
        return 'analysis_failed_parser_or_internal_error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class ExcludedByConfig:
    """Original type: skip_reason = [ ... | Excluded_by_config | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'ExcludedByConfig'

    @staticmethod
    def to_json() -> Any:
        return 'excluded_by_config'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class WrongLanguage:
    """Original type: skip_reason = [ ... | Wrong_language | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'WrongLanguage'

    @staticmethod
    def to_json() -> Any:
        return 'wrong_language'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class TooBig:
    """Original type: skip_reason = [ ... | Too_big | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'TooBig'

    @staticmethod
    def to_json() -> Any:
        return 'too_big'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Minified:
    """Original type: skip_reason = [ ... | Minified | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Minified'

    @staticmethod
    def to_json() -> Any:
        return 'minified'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Binary:
    """Original type: skip_reason = [ ... | Binary | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Binary'

    @staticmethod
    def to_json() -> Any:
        return 'binary'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class IrrelevantRule:
    """Original type: skip_reason = [ ... | Irrelevant_rule | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'IrrelevantRule'

    @staticmethod
    def to_json() -> Any:
        return 'irrelevant_rule'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class TooManyMatches:
    """Original type: skip_reason = [ ... | Too_many_matches | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'TooManyMatches'

    @staticmethod
    def to_json() -> Any:
        return 'too_many_matches'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class SkipReason:
    """Original type: skip_reason = [ ... ]"""

    value: Union[GitignorePatternsMatch, AlwaysSkipped, SemgrepignorePatternsMatch, CliIncludeFlagsDoNotMatch, CliExcludeFlagsMatch, ExceededSizeLimit, AnalysisFailedParserOrInternalError, ExcludedByConfig, WrongLanguage, TooBig, Minified, Binary, IrrelevantRule, TooManyMatches]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'SkipReason':
        if isinstance(x, str):
            if x == 'gitignore_patterns_match':
                return cls(GitignorePatternsMatch())
            if x == 'always_skipped':
                return cls(AlwaysSkipped())
            if x == 'semgrepignore_patterns_match':
                return cls(SemgrepignorePatternsMatch())
            if x == 'cli_include_flags_do_not_match':
                return cls(CliIncludeFlagsDoNotMatch())
            if x == 'cli_exclude_flags_match':
                return cls(CliExcludeFlagsMatch())
            if x == 'exceeded_size_limit':
                return cls(ExceededSizeLimit())
            if x == 'analysis_failed_parser_or_internal_error':
                return cls(AnalysisFailedParserOrInternalError())
            if x == 'excluded_by_config':
                return cls(ExcludedByConfig())
            if x == 'wrong_language':
                return cls(WrongLanguage())
            if x == 'too_big':
                return cls(TooBig())
            if x == 'minified':
                return cls(Minified())
            if x == 'binary':
                return cls(Binary())
            if x == 'irrelevant_rule':
                return cls(IrrelevantRule())
            if x == 'too_many_matches':
                return cls(TooManyMatches())
            _atd_bad_json('SkipReason', x)
        _atd_bad_json('SkipReason', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'SkipReason':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class SkippedTarget:
    """Original type: skipped_target = { ... }"""

    path: Fpath
    reason: SkipReason
    details: str
    rule_id: Optional[RuleId] = None

    @classmethod
    def from_json(cls, x: Any) -> 'SkippedTarget':
        if isinstance(x, dict):
            return cls(
                path=Fpath.from_json(x['path']) if 'path' in x else _atd_missing_json_field('SkippedTarget', 'path'),
                reason=SkipReason.from_json(x['reason']) if 'reason' in x else _atd_missing_json_field('SkippedTarget', 'reason'),
                details=_atd_read_string(x['details']) if 'details' in x else _atd_missing_json_field('SkippedTarget', 'details'),
                rule_id=RuleId.from_json(x['rule_id']) if 'rule_id' in x else None,
            )
        else:
            _atd_bad_json('SkippedTarget', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['path'] = (lambda x: x.to_json())(self.path)
        res['reason'] = (lambda x: x.to_json())(self.reason)
        res['details'] = _atd_write_string(self.details)
        if self.rule_id is not None:
            res['rule_id'] = (lambda x: x.to_json())(self.rule_id)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'SkippedTarget':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class SkippedRule:
    """Original type: skipped_rule = { ... }"""

    rule_id: RuleId
    details: str
    position: Position

    @classmethod
    def from_json(cls, x: Any) -> 'SkippedRule':
        if isinstance(x, dict):
            return cls(
                rule_id=RuleId.from_json(x['rule_id']) if 'rule_id' in x else _atd_missing_json_field('SkippedRule', 'rule_id'),
                details=_atd_read_string(x['details']) if 'details' in x else _atd_missing_json_field('SkippedRule', 'details'),
                position=Position.from_json(x['position']) if 'position' in x else _atd_missing_json_field('SkippedRule', 'position'),
            )
        else:
            _atd_bad_json('SkippedRule', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['rule_id'] = (lambda x: x.to_json())(self.rule_id)
        res['details'] = _atd_write_string(self.details)
        res['position'] = (lambda x: x.to_json())(self.position)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'SkippedRule':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Npm:
    """Original type: ecosystem = [ ... | Npm | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Npm'

    @staticmethod
    def to_json() -> Any:
        return 'npm'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Pypi:
    """Original type: ecosystem = [ ... | Pypi | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Pypi'

    @staticmethod
    def to_json() -> Any:
        return 'pypi'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Gem:
    """Original type: ecosystem = [ ... | Gem | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Gem'

    @staticmethod
    def to_json() -> Any:
        return 'gem'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Gomod:
    """Original type: ecosystem = [ ... | Gomod | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Gomod'

    @staticmethod
    def to_json() -> Any:
        return 'gomod'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Cargo:
    """Original type: ecosystem = [ ... | Cargo | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Cargo'

    @staticmethod
    def to_json() -> Any:
        return 'cargo'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Maven:
    """Original type: ecosystem = [ ... | Maven | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Maven'

    @staticmethod
    def to_json() -> Any:
        return 'maven'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Composer:
    """Original type: ecosystem = [ ... | Composer | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Composer'

    @staticmethod
    def to_json() -> Any:
        return 'composer'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Ecosystem:
    """Original type: ecosystem = [ ... ]"""

    value: Union[Npm, Pypi, Gem, Gomod, Cargo, Maven, Composer]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'Ecosystem':
        if isinstance(x, str):
            if x == 'npm':
                return cls(Npm())
            if x == 'pypi':
                return cls(Pypi())
            if x == 'gem':
                return cls(Gem())
            if x == 'gomod':
                return cls(Gomod())
            if x == 'cargo':
                return cls(Cargo())
            if x == 'maven':
                return cls(Maven())
            if x == 'composer':
                return cls(Composer())
            _atd_bad_json('Ecosystem', x)
        _atd_bad_json('Ecosystem', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'Ecosystem':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class FoundDependency:
    """Original type: found_dependency = { ... }"""

    package: str
    version: str
    ecosystem: Ecosystem
    allowed_hashes: Dict[str, List[str]]
    transitivity: Transitivity
    resolved_url: Optional[str] = None
    line_number: Optional[int] = None

    @classmethod
    def from_json(cls, x: Any) -> 'FoundDependency':
        if isinstance(x, dict):
            return cls(
                package=_atd_read_string(x['package']) if 'package' in x else _atd_missing_json_field('FoundDependency', 'package'),
                version=_atd_read_string(x['version']) if 'version' in x else _atd_missing_json_field('FoundDependency', 'version'),
                ecosystem=Ecosystem.from_json(x['ecosystem']) if 'ecosystem' in x else _atd_missing_json_field('FoundDependency', 'ecosystem'),
                allowed_hashes=_atd_read_assoc_object_into_dict(_atd_read_list(_atd_read_string))(x['allowed_hashes']) if 'allowed_hashes' in x else _atd_missing_json_field('FoundDependency', 'allowed_hashes'),
                transitivity=Transitivity.from_json(x['transitivity']) if 'transitivity' in x else _atd_missing_json_field('FoundDependency', 'transitivity'),
                resolved_url=_atd_read_string(x['resolved_url']) if 'resolved_url' in x else None,
                line_number=_atd_read_int(x['line_number']) if 'line_number' in x else None,
            )
        else:
            _atd_bad_json('FoundDependency', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['package'] = _atd_write_string(self.package)
        res['version'] = _atd_write_string(self.version)
        res['ecosystem'] = (lambda x: x.to_json())(self.ecosystem)
        res['allowed_hashes'] = _atd_write_assoc_dict_to_object(_atd_write_list(_atd_write_string))(self.allowed_hashes)
        res['transitivity'] = (lambda x: x.to_json())(self.transitivity)
        if self.resolved_url is not None:
            res['resolved_url'] = _atd_write_string(self.resolved_url)
        if self.line_number is not None:
            res['line_number'] = _atd_write_int(self.line_number)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'FoundDependency':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class DependencyPattern:
    """Original type: dependency_pattern = { ... }"""

    ecosystem: Ecosystem
    package: str
    semver_range: str

    @classmethod
    def from_json(cls, x: Any) -> 'DependencyPattern':
        if isinstance(x, dict):
            return cls(
                ecosystem=Ecosystem.from_json(x['ecosystem']) if 'ecosystem' in x else _atd_missing_json_field('DependencyPattern', 'ecosystem'),
                package=_atd_read_string(x['package']) if 'package' in x else _atd_missing_json_field('DependencyPattern', 'package'),
                semver_range=_atd_read_string(x['semver_range']) if 'semver_range' in x else _atd_missing_json_field('DependencyPattern', 'semver_range'),
            )
        else:
            _atd_bad_json('DependencyPattern', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['ecosystem'] = (lambda x: x.to_json())(self.ecosystem)
        res['package'] = _atd_write_string(self.package)
        res['semver_range'] = _atd_write_string(self.semver_range)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'DependencyPattern':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class DependencyMatch:
    """Original type: dependency_match = { ... }"""

    dependency_pattern: DependencyPattern
    found_dependency: FoundDependency
    lockfile: str

    @classmethod
    def from_json(cls, x: Any) -> 'DependencyMatch':
        if isinstance(x, dict):
            return cls(
                dependency_pattern=DependencyPattern.from_json(x['dependency_pattern']) if 'dependency_pattern' in x else _atd_missing_json_field('DependencyMatch', 'dependency_pattern'),
                found_dependency=FoundDependency.from_json(x['found_dependency']) if 'found_dependency' in x else _atd_missing_json_field('DependencyMatch', 'found_dependency'),
                lockfile=_atd_read_string(x['lockfile']) if 'lockfile' in x else _atd_missing_json_field('DependencyMatch', 'lockfile'),
            )
        else:
            _atd_bad_json('DependencyMatch', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['dependency_pattern'] = (lambda x: x.to_json())(self.dependency_pattern)
        res['found_dependency'] = (lambda x: x.to_json())(self.found_dependency)
        res['lockfile'] = _atd_write_string(self.lockfile)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'DependencyMatch':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class ScaInfo:
    """Original type: sca_info = { ... }"""

    reachable: bool
    reachability_rule: bool
    sca_finding_schema: int
    dependency_match: DependencyMatch

    @classmethod
    def from_json(cls, x: Any) -> 'ScaInfo':
        if isinstance(x, dict):
            return cls(
                reachable=_atd_read_bool(x['reachable']) if 'reachable' in x else _atd_missing_json_field('ScaInfo', 'reachable'),
                reachability_rule=_atd_read_bool(x['reachability_rule']) if 'reachability_rule' in x else _atd_missing_json_field('ScaInfo', 'reachability_rule'),
                sca_finding_schema=_atd_read_int(x['sca_finding_schema']) if 'sca_finding_schema' in x else _atd_missing_json_field('ScaInfo', 'sca_finding_schema'),
                dependency_match=DependencyMatch.from_json(x['dependency_match']) if 'dependency_match' in x else _atd_missing_json_field('ScaInfo', 'dependency_match'),
            )
        else:
            _atd_bad_json('ScaInfo', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['reachable'] = _atd_write_bool(self.reachable)
        res['reachability_rule'] = _atd_write_bool(self.reachability_rule)
        res['sca_finding_schema'] = _atd_write_int(self.sca_finding_schema)
        res['dependency_match'] = (lambda x: x.to_json())(self.dependency_match)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'ScaInfo':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class RuleIdDict:
    """Original type: rule_id_dict = { ... }"""

    id: RuleId

    @classmethod
    def from_json(cls, x: Any) -> 'RuleIdDict':
        if isinstance(x, dict):
            return cls(
                id=RuleId.from_json(x['id']) if 'id' in x else _atd_missing_json_field('RuleIdDict', 'id'),
            )
        else:
            _atd_bad_json('RuleIdDict', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['id'] = (lambda x: x.to_json())(self.id)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'RuleIdDict':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class RuleIdAndEngineKind:
    """Original type: rule_id_and_engine_kind"""

    value: Tuple[RuleId, EngineKind]

    @classmethod
    def from_json(cls, x: Any) -> 'RuleIdAndEngineKind':
        return cls((lambda x: (RuleId.from_json(x[0]), EngineKind.from_json(x[1])) if isinstance(x, list) and len(x) == 2 else _atd_bad_json('array of length 2', x))(x))

    def to_json(self) -> Any:
        return (lambda x: [(lambda x: x.to_json())(x[0]), (lambda x: x.to_json())(x[1])] if isinstance(x, tuple) and len(x) == 2 else _atd_bad_python('tuple of length 2', x))(self.value)

    @classmethod
    def from_json_string(cls, x: str) -> 'RuleIdAndEngineKind':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class PositionBis:
    """Original type: position_bis = { ... }"""

    line: int
    col: int

    @classmethod
    def from_json(cls, x: Any) -> 'PositionBis':
        if isinstance(x, dict):
            return cls(
                line=_atd_read_int(x['line']) if 'line' in x else _atd_missing_json_field('PositionBis', 'line'),
                col=_atd_read_int(x['col']) if 'col' in x else _atd_missing_json_field('PositionBis', 'col'),
            )
        else:
            _atd_bad_json('PositionBis', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['line'] = _atd_write_int(self.line)
        res['col'] = _atd_write_int(self.col)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'PositionBis':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class FixRegex:
    """Original type: fix_regex = { ... }"""

    regex: str
    replacement: str
    count: Optional[int] = None

    @classmethod
    def from_json(cls, x: Any) -> 'FixRegex':
        if isinstance(x, dict):
            return cls(
                regex=_atd_read_string(x['regex']) if 'regex' in x else _atd_missing_json_field('FixRegex', 'regex'),
                replacement=_atd_read_string(x['replacement']) if 'replacement' in x else _atd_missing_json_field('FixRegex', 'replacement'),
                count=_atd_read_int(x['count']) if 'count' in x else None,
            )
        else:
            _atd_bad_json('FixRegex', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['regex'] = _atd_write_string(self.regex)
        res['replacement'] = _atd_write_string(self.replacement)
        if self.count is not None:
            res['count'] = _atd_write_int(self.count)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'FixRegex':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class FindingHashes:
    """Original type: finding_hashes = { ... }"""

    start_line_hash: str
    end_line_hash: str
    code_hash: str
    pattern_hash: str

    @classmethod
    def from_json(cls, x: Any) -> 'FindingHashes':
        if isinstance(x, dict):
            return cls(
                start_line_hash=_atd_read_string(x['start_line_hash']) if 'start_line_hash' in x else _atd_missing_json_field('FindingHashes', 'start_line_hash'),
                end_line_hash=_atd_read_string(x['end_line_hash']) if 'end_line_hash' in x else _atd_missing_json_field('FindingHashes', 'end_line_hash'),
                code_hash=_atd_read_string(x['code_hash']) if 'code_hash' in x else _atd_missing_json_field('FindingHashes', 'code_hash'),
                pattern_hash=_atd_read_string(x['pattern_hash']) if 'pattern_hash' in x else _atd_missing_json_field('FindingHashes', 'pattern_hash'),
            )
        else:
            _atd_bad_json('FindingHashes', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['start_line_hash'] = _atd_write_string(self.start_line_hash)
        res['end_line_hash'] = _atd_write_string(self.end_line_hash)
        res['code_hash'] = _atd_write_string(self.code_hash)
        res['pattern_hash'] = _atd_write_string(self.pattern_hash)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'FindingHashes':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CliMatchDataflowTrace:
    """Original type: cli_match_dataflow_trace = { ... }"""

    taint_source: Optional[CliMatchCallTrace] = None
    intermediate_vars: Optional[List[CliMatchIntermediateVar]] = None
    taint_sink: Optional[CliMatchCallTrace] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CliMatchDataflowTrace':
        if isinstance(x, dict):
            return cls(
                taint_source=CliMatchCallTrace.from_json(x['taint_source']) if 'taint_source' in x else None,
                intermediate_vars=_atd_read_list(CliMatchIntermediateVar.from_json)(x['intermediate_vars']) if 'intermediate_vars' in x else None,
                taint_sink=CliMatchCallTrace.from_json(x['taint_sink']) if 'taint_sink' in x else None,
            )
        else:
            _atd_bad_json('CliMatchDataflowTrace', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        if self.taint_source is not None:
            res['taint_source'] = (lambda x: x.to_json())(self.taint_source)
        if self.intermediate_vars is not None:
            res['intermediate_vars'] = _atd_write_list((lambda x: x.to_json()))(self.intermediate_vars)
        if self.taint_sink is not None:
            res['taint_sink'] = (lambda x: x.to_json())(self.taint_sink)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliMatchDataflowTrace':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class Finding:
    """Original type: finding = { ... }"""

    check_id: RuleId
    path: Fpath
    line: int
    column: int
    end_line: int
    end_column: int
    message: str
    severity: int
    index: int
    commit_date: str
    syntactic_id: str
    metadata: RawJson
    is_blocking: bool
    match_based_id: Optional[str] = None
    hashes: Optional[FindingHashes] = None
    fixed_lines: Optional[List[str]] = None
    sca_info: Optional[ScaInfo] = None
    dataflow_trace: Optional[CliMatchDataflowTrace] = None

    @classmethod
    def from_json(cls, x: Any) -> 'Finding':
        if isinstance(x, dict):
            return cls(
                check_id=RuleId.from_json(x['check_id']) if 'check_id' in x else _atd_missing_json_field('Finding', 'check_id'),
                path=Fpath.from_json(x['path']) if 'path' in x else _atd_missing_json_field('Finding', 'path'),
                line=_atd_read_int(x['line']) if 'line' in x else _atd_missing_json_field('Finding', 'line'),
                column=_atd_read_int(x['column']) if 'column' in x else _atd_missing_json_field('Finding', 'column'),
                end_line=_atd_read_int(x['end_line']) if 'end_line' in x else _atd_missing_json_field('Finding', 'end_line'),
                end_column=_atd_read_int(x['end_column']) if 'end_column' in x else _atd_missing_json_field('Finding', 'end_column'),
                message=_atd_read_string(x['message']) if 'message' in x else _atd_missing_json_field('Finding', 'message'),
                severity=_atd_read_int(x['severity']) if 'severity' in x else _atd_missing_json_field('Finding', 'severity'),
                index=_atd_read_int(x['index']) if 'index' in x else _atd_missing_json_field('Finding', 'index'),
                commit_date=_atd_read_string(x['commit_date']) if 'commit_date' in x else _atd_missing_json_field('Finding', 'commit_date'),
                syntactic_id=_atd_read_string(x['syntactic_id']) if 'syntactic_id' in x else _atd_missing_json_field('Finding', 'syntactic_id'),
                metadata=RawJson.from_json(x['metadata']) if 'metadata' in x else _atd_missing_json_field('Finding', 'metadata'),
                is_blocking=_atd_read_bool(x['is_blocking']) if 'is_blocking' in x else _atd_missing_json_field('Finding', 'is_blocking'),
                match_based_id=_atd_read_string(x['match_based_id']) if 'match_based_id' in x else None,
                hashes=FindingHashes.from_json(x['hashes']) if 'hashes' in x else None,
                fixed_lines=_atd_read_list(_atd_read_string)(x['fixed_lines']) if 'fixed_lines' in x else None,
                sca_info=ScaInfo.from_json(x['sca_info']) if 'sca_info' in x else None,
                dataflow_trace=CliMatchDataflowTrace.from_json(x['dataflow_trace']) if 'dataflow_trace' in x else None,
            )
        else:
            _atd_bad_json('Finding', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['check_id'] = (lambda x: x.to_json())(self.check_id)
        res['path'] = (lambda x: x.to_json())(self.path)
        res['line'] = _atd_write_int(self.line)
        res['column'] = _atd_write_int(self.column)
        res['end_line'] = _atd_write_int(self.end_line)
        res['end_column'] = _atd_write_int(self.end_column)
        res['message'] = _atd_write_string(self.message)
        res['severity'] = _atd_write_int(self.severity)
        res['index'] = _atd_write_int(self.index)
        res['commit_date'] = _atd_write_string(self.commit_date)
        res['syntactic_id'] = _atd_write_string(self.syntactic_id)
        res['metadata'] = (lambda x: x.to_json())(self.metadata)
        res['is_blocking'] = _atd_write_bool(self.is_blocking)
        if self.match_based_id is not None:
            res['match_based_id'] = _atd_write_string(self.match_based_id)
        if self.hashes is not None:
            res['hashes'] = (lambda x: x.to_json())(self.hashes)
        if self.fixed_lines is not None:
            res['fixed_lines'] = _atd_write_list(_atd_write_string)(self.fixed_lines)
        if self.sca_info is not None:
            res['sca_info'] = (lambda x: x.to_json())(self.sca_info)
        if self.dataflow_trace is not None:
            res['dataflow_trace'] = (lambda x: x.to_json())(self.dataflow_trace)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'Finding':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class ErrorSpan:
    """Original type: error_span = { ... }"""

    file: Fpath
    start: PositionBis
    end: PositionBis
    source_hash: Optional[str] = None
    config_start: Optional[Optional[PositionBis]] = None
    config_end: Optional[Optional[PositionBis]] = None
    config_path: Optional[Optional[List[str]]] = None
    context_start: Optional[Optional[PositionBis]] = None
    context_end: Optional[Optional[PositionBis]] = None

    @classmethod
    def from_json(cls, x: Any) -> 'ErrorSpan':
        if isinstance(x, dict):
            return cls(
                file=Fpath.from_json(x['file']) if 'file' in x else _atd_missing_json_field('ErrorSpan', 'file'),
                start=PositionBis.from_json(x['start']) if 'start' in x else _atd_missing_json_field('ErrorSpan', 'start'),
                end=PositionBis.from_json(x['end']) if 'end' in x else _atd_missing_json_field('ErrorSpan', 'end'),
                source_hash=_atd_read_string(x['source_hash']) if 'source_hash' in x else None,
                config_start=_atd_read_nullable(PositionBis.from_json)(x['config_start']) if 'config_start' in x else None,
                config_end=_atd_read_nullable(PositionBis.from_json)(x['config_end']) if 'config_end' in x else None,
                config_path=_atd_read_nullable(_atd_read_list(_atd_read_string))(x['config_path']) if 'config_path' in x else None,
                context_start=_atd_read_nullable(PositionBis.from_json)(x['context_start']) if 'context_start' in x else None,
                context_end=_atd_read_nullable(PositionBis.from_json)(x['context_end']) if 'context_end' in x else None,
            )
        else:
            _atd_bad_json('ErrorSpan', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['file'] = (lambda x: x.to_json())(self.file)
        res['start'] = (lambda x: x.to_json())(self.start)
        res['end'] = (lambda x: x.to_json())(self.end)
        if self.source_hash is not None:
            res['source_hash'] = _atd_write_string(self.source_hash)
        if self.config_start is not None:
            res['config_start'] = _atd_write_nullable((lambda x: x.to_json()))(self.config_start)
        if self.config_end is not None:
            res['config_end'] = _atd_write_nullable((lambda x: x.to_json()))(self.config_end)
        if self.config_path is not None:
            res['config_path'] = _atd_write_nullable(_atd_write_list(_atd_write_string))(self.config_path)
        if self.context_start is not None:
            res['context_start'] = _atd_write_nullable((lambda x: x.to_json()))(self.context_start)
        if self.context_end is not None:
            res['context_end'] = _atd_write_nullable((lambda x: x.to_json()))(self.context_end)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'ErrorSpan':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CveResult:
    """Original type: cve_result = { ... }"""

    url: str
    filename: str
    funcnames: List[str]

    @classmethod
    def from_json(cls, x: Any) -> 'CveResult':
        if isinstance(x, dict):
            return cls(
                url=_atd_read_string(x['url']) if 'url' in x else _atd_missing_json_field('CveResult', 'url'),
                filename=_atd_read_string(x['filename']) if 'filename' in x else _atd_missing_json_field('CveResult', 'filename'),
                funcnames=_atd_read_list(_atd_read_string)(x['funcnames']) if 'funcnames' in x else _atd_missing_json_field('CveResult', 'funcnames'),
            )
        else:
            _atd_bad_json('CveResult', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['url'] = _atd_write_string(self.url)
        res['filename'] = _atd_write_string(self.filename)
        res['funcnames'] = _atd_write_list(_atd_write_string)(self.funcnames)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CveResult':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CveResults:
    """Original type: cve_results"""

    value: List[CveResult]

    @classmethod
    def from_json(cls, x: Any) -> 'CveResults':
        return cls(_atd_read_list(CveResult.from_json)(x))

    def to_json(self) -> Any:
        return _atd_write_list((lambda x: x.to_json()))(self.value)

    @classmethod
    def from_json_string(cls, x: str) -> 'CveResults':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreTiming:
    """Original type: core_timing = { ... }"""

    targets: List[TargetTime]
    rules: List[RuleId]
    max_memory_bytes: int
    rules_parse_time: Optional[float] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CoreTiming':
        if isinstance(x, dict):
            return cls(
                targets=_atd_read_list(TargetTime.from_json)(x['targets']) if 'targets' in x else _atd_missing_json_field('CoreTiming', 'targets'),
                rules=_atd_read_list(RuleId.from_json)(x['rules']) if 'rules' in x else _atd_missing_json_field('CoreTiming', 'rules'),
                max_memory_bytes=_atd_read_int(x['max_memory_bytes']) if 'max_memory_bytes' in x else _atd_missing_json_field('CoreTiming', 'max_memory_bytes'),
                rules_parse_time=_atd_read_float(x['rules_parse_time']) if 'rules_parse_time' in x else None,
            )
        else:
            _atd_bad_json('CoreTiming', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['targets'] = _atd_write_list((lambda x: x.to_json()))(self.targets)
        res['rules'] = _atd_write_list((lambda x: x.to_json()))(self.rules)
        res['max_memory_bytes'] = _atd_write_int(self.max_memory_bytes)
        if self.rules_parse_time is not None:
            res['rules_parse_time'] = _atd_write_float(self.rules_parse_time)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreTiming':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreStats:
    """Original type: core_stats = { ... }"""

    okfiles: int
    errorfiles: int

    @classmethod
    def from_json(cls, x: Any) -> 'CoreStats':
        if isinstance(x, dict):
            return cls(
                okfiles=_atd_read_int(x['okfiles']) if 'okfiles' in x else _atd_missing_json_field('CoreStats', 'okfiles'),
                errorfiles=_atd_read_int(x['errorfiles']) if 'errorfiles' in x else _atd_missing_json_field('CoreStats', 'errorfiles'),
            )
        else:
            _atd_bad_json('CoreStats', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['okfiles'] = _atd_write_int(self.okfiles)
        res['errorfiles'] = _atd_write_int(self.errorfiles)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreStats':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Error:
    """Original type: core_severity = [ ... | Error | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Error'

    @staticmethod
    def to_json() -> Any:
        return 'error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class Warning:
    """Original type: core_severity = [ ... | Warning | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Warning'

    @staticmethod
    def to_json() -> Any:
        return 'warning'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreSeverity:
    """Original type: core_severity = [ ... ]"""

    value: Union[Error, Warning]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'CoreSeverity':
        if isinstance(x, str):
            if x == 'error':
                return cls(Error())
            if x == 'warning':
                return cls(Warning())
            _atd_bad_json('CoreSeverity', x)
        _atd_bad_json('CoreSeverity', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreSeverity':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class LexicalError:
    """Original type: core_error_kind = [ ... | LexicalError | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'LexicalError'

    @staticmethod
    def to_json() -> Any:
        return 'Lexical error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class ParseError:
    """Original type: core_error_kind = [ ... | ParseError | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'ParseError'

    @staticmethod
    def to_json() -> Any:
        return 'Syntax error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class SpecifiedParseError:
    """Original type: core_error_kind = [ ... | SpecifiedParseError | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'SpecifiedParseError'

    @staticmethod
    def to_json() -> Any:
        return 'Other syntax error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class AstBuilderError:
    """Original type: core_error_kind = [ ... | AstBuilderError | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'AstBuilderError'

    @staticmethod
    def to_json() -> Any:
        return 'AST builder error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class RuleParseError:
    """Original type: core_error_kind = [ ... | RuleParseError | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'RuleParseError'

    @staticmethod
    def to_json() -> Any:
        return 'Rule parse error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class PatternParseError:
    """Original type: core_error_kind = [ ... | PatternParseError of ... | ... ]"""

    value: List[str]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'PatternParseError'

    def to_json(self) -> Any:
        return ['Pattern parse error', _atd_write_list(_atd_write_string)(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class InvalidYaml:
    """Original type: core_error_kind = [ ... | InvalidYaml | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'InvalidYaml'

    @staticmethod
    def to_json() -> Any:
        return 'Invalid YAML'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class MatchingError:
    """Original type: core_error_kind = [ ... | MatchingError | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'MatchingError'

    @staticmethod
    def to_json() -> Any:
        return 'Internal matching error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class SemgrepMatchFound:
    """Original type: core_error_kind = [ ... | SemgrepMatchFound | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'SemgrepMatchFound'

    @staticmethod
    def to_json() -> Any:
        return 'Semgrep match found'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class TooManyMatches_:
    """Original type: core_error_kind = [ ... | TooManyMatches | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'TooManyMatches_'

    @staticmethod
    def to_json() -> Any:
        return 'Too many matches'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class FatalError:
    """Original type: core_error_kind = [ ... | FatalError | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'FatalError'

    @staticmethod
    def to_json() -> Any:
        return 'Fatal error'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class Timeout:
    """Original type: core_error_kind = [ ... | Timeout | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'Timeout'

    @staticmethod
    def to_json() -> Any:
        return 'Timeout'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class OutOfMemory:
    """Original type: core_error_kind = [ ... | OutOfMemory | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'OutOfMemory'

    @staticmethod
    def to_json() -> Any:
        return 'Out of memory'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class TimeoutDuringInterfile:
    """Original type: core_error_kind = [ ... | TimeoutDuringInterfile | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'TimeoutDuringInterfile'

    @staticmethod
    def to_json() -> Any:
        return 'Timeout during interfile analysis'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class OutOfMemoryDuringInterfile:
    """Original type: core_error_kind = [ ... | OutOfMemoryDuringInterfile | ... ]"""

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'OutOfMemoryDuringInterfile'

    @staticmethod
    def to_json() -> Any:
        return 'OOM during interfile analysis'

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class PartialParsing:
    """Original type: core_error_kind = [ ... | PartialParsing of ... | ... ]"""

    value: List[Location]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return 'PartialParsing'

    def to_json(self) -> Any:
        return ['PartialParsing', _atd_write_list((lambda x: x.to_json()))(self.value)]

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True, order=True)
class CoreErrorKind:
    """Original type: core_error_kind = [ ... ]"""

    value: Union[LexicalError, ParseError, SpecifiedParseError, AstBuilderError, RuleParseError, PatternParseError, InvalidYaml, MatchingError, SemgrepMatchFound, TooManyMatches_, FatalError, Timeout, OutOfMemory, TimeoutDuringInterfile, OutOfMemoryDuringInterfile, PartialParsing]

    @property
    def kind(self) -> str:
        """Name of the class representing this variant."""
        return self.value.kind

    @classmethod
    def from_json(cls, x: Any) -> 'CoreErrorKind':
        if isinstance(x, str):
            if x == 'Lexical error':
                return cls(LexicalError())
            if x == 'Syntax error':
                return cls(ParseError())
            if x == 'Other syntax error':
                return cls(SpecifiedParseError())
            if x == 'AST builder error':
                return cls(AstBuilderError())
            if x == 'Rule parse error':
                return cls(RuleParseError())
            if x == 'Invalid YAML':
                return cls(InvalidYaml())
            if x == 'Internal matching error':
                return cls(MatchingError())
            if x == 'Semgrep match found':
                return cls(SemgrepMatchFound())
            if x == 'Too many matches':
                return cls(TooManyMatches_())
            if x == 'Fatal error':
                return cls(FatalError())
            if x == 'Timeout':
                return cls(Timeout())
            if x == 'Out of memory':
                return cls(OutOfMemory())
            if x == 'Timeout during interfile analysis':
                return cls(TimeoutDuringInterfile())
            if x == 'OOM during interfile analysis':
                return cls(OutOfMemoryDuringInterfile())
            _atd_bad_json('CoreErrorKind', x)
        if isinstance(x, List) and len(x) == 2:
            cons = x[0]
            if cons == 'Pattern parse error':
                return cls(PatternParseError(_atd_read_list(_atd_read_string)(x[1])))
            if cons == 'PartialParsing':
                return cls(PartialParsing(_atd_read_list(Location.from_json)(x[1])))
            _atd_bad_json('CoreErrorKind', x)
        _atd_bad_json('CoreErrorKind', x)

    def to_json(self) -> Any:
        return self.value.to_json()

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreErrorKind':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreError:
    """Original type: core_error = { ... }"""

    error_type: CoreErrorKind
    severity: CoreSeverity
    location: Location
    message: str
    rule_id: Optional[RuleId] = None
    details: Optional[str] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CoreError':
        if isinstance(x, dict):
            return cls(
                error_type=CoreErrorKind.from_json(x['error_type']) if 'error_type' in x else _atd_missing_json_field('CoreError', 'error_type'),
                severity=CoreSeverity.from_json(x['severity']) if 'severity' in x else _atd_missing_json_field('CoreError', 'severity'),
                location=Location.from_json(x['location']) if 'location' in x else _atd_missing_json_field('CoreError', 'location'),
                message=_atd_read_string(x['message']) if 'message' in x else _atd_missing_json_field('CoreError', 'message'),
                rule_id=RuleId.from_json(x['rule_id']) if 'rule_id' in x else None,
                details=_atd_read_string(x['details']) if 'details' in x else None,
            )
        else:
            _atd_bad_json('CoreError', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['error_type'] = (lambda x: x.to_json())(self.error_type)
        res['severity'] = (lambda x: x.to_json())(self.severity)
        res['location'] = (lambda x: x.to_json())(self.location)
        res['message'] = _atd_write_string(self.message)
        if self.rule_id is not None:
            res['rule_id'] = (lambda x: x.to_json())(self.rule_id)
        if self.details is not None:
            res['details'] = _atd_write_string(self.details)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreError':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CoreMatchResults:
    """Original type: core_match_results = { ... }"""

    matches: List[CoreMatch]
    errors: List[CoreError]
    stats: CoreStats
    rules_by_engine: List[RuleIdAndEngineKind]
    engine_requested: EngineKind
    skipped_targets: Optional[List[SkippedTarget]] = None
    skipped_rules: Optional[List[SkippedRule]] = None
    explanations: Optional[List[MatchingExplanation]] = None
    time: Optional[CoreTiming] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CoreMatchResults':
        if isinstance(x, dict):
            return cls(
                matches=_atd_read_list(CoreMatch.from_json)(x['matches']) if 'matches' in x else _atd_missing_json_field('CoreMatchResults', 'matches'),
                errors=_atd_read_list(CoreError.from_json)(x['errors']) if 'errors' in x else _atd_missing_json_field('CoreMatchResults', 'errors'),
                stats=CoreStats.from_json(x['stats']) if 'stats' in x else _atd_missing_json_field('CoreMatchResults', 'stats'),
                rules_by_engine=_atd_read_list(RuleIdAndEngineKind.from_json)(x['rules_by_engine']) if 'rules_by_engine' in x else _atd_missing_json_field('CoreMatchResults', 'rules_by_engine'),
                engine_requested=EngineKind.from_json(x['engine_requested']) if 'engine_requested' in x else _atd_missing_json_field('CoreMatchResults', 'engine_requested'),
                skipped_targets=_atd_read_list(SkippedTarget.from_json)(x['skipped']) if 'skipped' in x else None,
                skipped_rules=_atd_read_list(SkippedRule.from_json)(x['skipped_rules']) if 'skipped_rules' in x else None,
                explanations=_atd_read_list(MatchingExplanation.from_json)(x['explanations']) if 'explanations' in x else None,
                time=CoreTiming.from_json(x['time']) if 'time' in x else None,
            )
        else:
            _atd_bad_json('CoreMatchResults', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['matches'] = _atd_write_list((lambda x: x.to_json()))(self.matches)
        res['errors'] = _atd_write_list((lambda x: x.to_json()))(self.errors)
        res['stats'] = (lambda x: x.to_json())(self.stats)
        res['rules_by_engine'] = _atd_write_list((lambda x: x.to_json()))(self.rules_by_engine)
        res['engine_requested'] = (lambda x: x.to_json())(self.engine_requested)
        if self.skipped_targets is not None:
            res['skipped'] = _atd_write_list((lambda x: x.to_json()))(self.skipped_targets)
        if self.skipped_rules is not None:
            res['skipped_rules'] = _atd_write_list((lambda x: x.to_json()))(self.skipped_rules)
        if self.explanations is not None:
            res['explanations'] = _atd_write_list((lambda x: x.to_json()))(self.explanations)
        if self.time is not None:
            res['time'] = (lambda x: x.to_json())(self.time)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CoreMatchResults':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliTargetTimes:
    """Original type: cli_target_times = { ... }"""

    path: Fpath
    num_bytes: int
    match_times: List[float]
    parse_times: List[float]
    run_time: float

    @classmethod
    def from_json(cls, x: Any) -> 'CliTargetTimes':
        if isinstance(x, dict):
            return cls(
                path=Fpath.from_json(x['path']) if 'path' in x else _atd_missing_json_field('CliTargetTimes', 'path'),
                num_bytes=_atd_read_int(x['num_bytes']) if 'num_bytes' in x else _atd_missing_json_field('CliTargetTimes', 'num_bytes'),
                match_times=_atd_read_list(_atd_read_float)(x['match_times']) if 'match_times' in x else _atd_missing_json_field('CliTargetTimes', 'match_times'),
                parse_times=_atd_read_list(_atd_read_float)(x['parse_times']) if 'parse_times' in x else _atd_missing_json_field('CliTargetTimes', 'parse_times'),
                run_time=_atd_read_float(x['run_time']) if 'run_time' in x else _atd_missing_json_field('CliTargetTimes', 'run_time'),
            )
        else:
            _atd_bad_json('CliTargetTimes', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['path'] = (lambda x: x.to_json())(self.path)
        res['num_bytes'] = _atd_write_int(self.num_bytes)
        res['match_times'] = _atd_write_list(_atd_write_float)(self.match_times)
        res['parse_times'] = _atd_write_list(_atd_write_float)(self.parse_times)
        res['run_time'] = _atd_write_float(self.run_time)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliTargetTimes':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliTiming:
    """Original type: cli_timing = { ... }"""

    rules: List[RuleIdDict]
    rules_parse_time: float
    profiling_times: Dict[str, float]
    targets: List[CliTargetTimes]
    total_bytes: int
    max_memory_bytes: Optional[int] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CliTiming':
        if isinstance(x, dict):
            return cls(
                rules=_atd_read_list(RuleIdDict.from_json)(x['rules']) if 'rules' in x else _atd_missing_json_field('CliTiming', 'rules'),
                rules_parse_time=_atd_read_float(x['rules_parse_time']) if 'rules_parse_time' in x else _atd_missing_json_field('CliTiming', 'rules_parse_time'),
                profiling_times=_atd_read_assoc_object_into_dict(_atd_read_float)(x['profiling_times']) if 'profiling_times' in x else _atd_missing_json_field('CliTiming', 'profiling_times'),
                targets=_atd_read_list(CliTargetTimes.from_json)(x['targets']) if 'targets' in x else _atd_missing_json_field('CliTiming', 'targets'),
                total_bytes=_atd_read_int(x['total_bytes']) if 'total_bytes' in x else _atd_missing_json_field('CliTiming', 'total_bytes'),
                max_memory_bytes=_atd_read_int(x['max_memory_bytes']) if 'max_memory_bytes' in x else None,
            )
        else:
            _atd_bad_json('CliTiming', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['rules'] = _atd_write_list((lambda x: x.to_json()))(self.rules)
        res['rules_parse_time'] = _atd_write_float(self.rules_parse_time)
        res['profiling_times'] = _atd_write_assoc_dict_to_object(_atd_write_float)(self.profiling_times)
        res['targets'] = _atd_write_list((lambda x: x.to_json()))(self.targets)
        res['total_bytes'] = _atd_write_int(self.total_bytes)
        if self.max_memory_bytes is not None:
            res['max_memory_bytes'] = _atd_write_int(self.max_memory_bytes)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliTiming':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliSkippedTarget:
    """Original type: cli_skipped_target = { ... }"""

    path: Fpath
    reason: SkipReason

    @classmethod
    def from_json(cls, x: Any) -> 'CliSkippedTarget':
        if isinstance(x, dict):
            return cls(
                path=Fpath.from_json(x['path']) if 'path' in x else _atd_missing_json_field('CliSkippedTarget', 'path'),
                reason=SkipReason.from_json(x['reason']) if 'reason' in x else _atd_missing_json_field('CliSkippedTarget', 'reason'),
            )
        else:
            _atd_bad_json('CliSkippedTarget', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['path'] = (lambda x: x.to_json())(self.path)
        res['reason'] = (lambda x: x.to_json())(self.reason)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliSkippedTarget':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliPaths:
    """Original type: cli_paths = { ... }"""

    scanned: List[str]
    _comment: Optional[str] = None
    skipped: Optional[List[CliSkippedTarget]] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CliPaths':
        if isinstance(x, dict):
            return cls(
                scanned=_atd_read_list(_atd_read_string)(x['scanned']) if 'scanned' in x else _atd_missing_json_field('CliPaths', 'scanned'),
                _comment=_atd_read_string(x['_comment']) if '_comment' in x else None,
                skipped=_atd_read_list(CliSkippedTarget.from_json)(x['skipped']) if 'skipped' in x else None,
            )
        else:
            _atd_bad_json('CliPaths', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['scanned'] = _atd_write_list(_atd_write_string)(self.scanned)
        if self._comment is not None:
            res['_comment'] = _atd_write_string(self._comment)
        if self.skipped is not None:
            res['skipped'] = _atd_write_list((lambda x: x.to_json()))(self.skipped)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliPaths':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliOutputExtra:
    """Original type: cli_output_extra = { ... }"""

    paths: CliPaths
    time: Optional[CliTiming] = None
    explanations: Optional[List[MatchingExplanation]] = None
    rules_by_engine: Optional[List[RuleIdAndEngineKind]] = None
    engine_requested: Optional[EngineKind] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CliOutputExtra':
        if isinstance(x, dict):
            return cls(
                paths=CliPaths.from_json(x['paths']) if 'paths' in x else _atd_missing_json_field('CliOutputExtra', 'paths'),
                time=CliTiming.from_json(x['time']) if 'time' in x else None,
                explanations=_atd_read_list(MatchingExplanation.from_json)(x['explanations']) if 'explanations' in x else None,
                rules_by_engine=_atd_read_list(RuleIdAndEngineKind.from_json)(x['rules_by_engine']) if 'rules_by_engine' in x else None,
                engine_requested=EngineKind.from_json(x['engine_requested']) if 'engine_requested' in x else None,
            )
        else:
            _atd_bad_json('CliOutputExtra', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['paths'] = (lambda x: x.to_json())(self.paths)
        if self.time is not None:
            res['time'] = (lambda x: x.to_json())(self.time)
        if self.explanations is not None:
            res['explanations'] = _atd_write_list((lambda x: x.to_json()))(self.explanations)
        if self.rules_by_engine is not None:
            res['rules_by_engine'] = _atd_write_list((lambda x: x.to_json()))(self.rules_by_engine)
        if self.engine_requested is not None:
            res['engine_requested'] = (lambda x: x.to_json())(self.engine_requested)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliOutputExtra':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliMatchExtra:
    """Original type: cli_match_extra = { ... }"""

    fingerprint: str
    lines: str
    message: str
    metadata: RawJson
    severity: str
    metavars: Optional[Metavars] = None
    fix: Optional[str] = None
    fix_regex: Optional[FixRegex] = None
    is_ignored: Optional[bool] = None
    sca_info: Optional[ScaInfo] = None
    fixed_lines: Optional[List[str]] = None
    dataflow_trace: Optional[CliMatchDataflowTrace] = None
    engine_kind: Optional[EngineKind] = None
    extra_extra: Optional[RawJson] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CliMatchExtra':
        if isinstance(x, dict):
            return cls(
                fingerprint=_atd_read_string(x['fingerprint']) if 'fingerprint' in x else _atd_missing_json_field('CliMatchExtra', 'fingerprint'),
                lines=_atd_read_string(x['lines']) if 'lines' in x else _atd_missing_json_field('CliMatchExtra', 'lines'),
                message=_atd_read_string(x['message']) if 'message' in x else _atd_missing_json_field('CliMatchExtra', 'message'),
                metadata=RawJson.from_json(x['metadata']) if 'metadata' in x else _atd_missing_json_field('CliMatchExtra', 'metadata'),
                severity=_atd_read_string(x['severity']) if 'severity' in x else _atd_missing_json_field('CliMatchExtra', 'severity'),
                metavars=Metavars.from_json(x['metavars']) if 'metavars' in x else None,
                fix=_atd_read_string(x['fix']) if 'fix' in x else None,
                fix_regex=FixRegex.from_json(x['fix_regex']) if 'fix_regex' in x else None,
                is_ignored=_atd_read_bool(x['is_ignored']) if 'is_ignored' in x else None,
                sca_info=ScaInfo.from_json(x['sca_info']) if 'sca_info' in x else None,
                fixed_lines=_atd_read_list(_atd_read_string)(x['fixed_lines']) if 'fixed_lines' in x else None,
                dataflow_trace=CliMatchDataflowTrace.from_json(x['dataflow_trace']) if 'dataflow_trace' in x else None,
                engine_kind=EngineKind.from_json(x['engine_kind']) if 'engine_kind' in x else None,
                extra_extra=RawJson.from_json(x['extra_extra']) if 'extra_extra' in x else None,
            )
        else:
            _atd_bad_json('CliMatchExtra', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['fingerprint'] = _atd_write_string(self.fingerprint)
        res['lines'] = _atd_write_string(self.lines)
        res['message'] = _atd_write_string(self.message)
        res['metadata'] = (lambda x: x.to_json())(self.metadata)
        res['severity'] = _atd_write_string(self.severity)
        if self.metavars is not None:
            res['metavars'] = (lambda x: x.to_json())(self.metavars)
        if self.fix is not None:
            res['fix'] = _atd_write_string(self.fix)
        if self.fix_regex is not None:
            res['fix_regex'] = (lambda x: x.to_json())(self.fix_regex)
        if self.is_ignored is not None:
            res['is_ignored'] = _atd_write_bool(self.is_ignored)
        if self.sca_info is not None:
            res['sca_info'] = (lambda x: x.to_json())(self.sca_info)
        if self.fixed_lines is not None:
            res['fixed_lines'] = _atd_write_list(_atd_write_string)(self.fixed_lines)
        if self.dataflow_trace is not None:
            res['dataflow_trace'] = (lambda x: x.to_json())(self.dataflow_trace)
        if self.engine_kind is not None:
            res['engine_kind'] = (lambda x: x.to_json())(self.engine_kind)
        if self.extra_extra is not None:
            res['extra_extra'] = (lambda x: x.to_json())(self.extra_extra)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliMatchExtra':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliMatch:
    """Original type: cli_match = { ... }"""

    check_id: RuleId
    path: Fpath
    start: Position
    end: Position
    extra: CliMatchExtra

    @classmethod
    def from_json(cls, x: Any) -> 'CliMatch':
        if isinstance(x, dict):
            return cls(
                check_id=RuleId.from_json(x['check_id']) if 'check_id' in x else _atd_missing_json_field('CliMatch', 'check_id'),
                path=Fpath.from_json(x['path']) if 'path' in x else _atd_missing_json_field('CliMatch', 'path'),
                start=Position.from_json(x['start']) if 'start' in x else _atd_missing_json_field('CliMatch', 'start'),
                end=Position.from_json(x['end']) if 'end' in x else _atd_missing_json_field('CliMatch', 'end'),
                extra=CliMatchExtra.from_json(x['extra']) if 'extra' in x else _atd_missing_json_field('CliMatch', 'extra'),
            )
        else:
            _atd_bad_json('CliMatch', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['check_id'] = (lambda x: x.to_json())(self.check_id)
        res['path'] = (lambda x: x.to_json())(self.path)
        res['start'] = (lambda x: x.to_json())(self.start)
        res['end'] = (lambda x: x.to_json())(self.end)
        res['extra'] = (lambda x: x.to_json())(self.extra)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliMatch':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliError:
    """Original type: cli_error = { ... }"""

    code: int
    level: str
    type_: str
    rule_id: Optional[RuleId] = None
    message: Optional[str] = None
    path: Optional[Fpath] = None
    long_msg: Optional[str] = None
    short_msg: Optional[str] = None
    spans: Optional[List[ErrorSpan]] = None
    help: Optional[str] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CliError':
        if isinstance(x, dict):
            return cls(
                code=_atd_read_int(x['code']) if 'code' in x else _atd_missing_json_field('CliError', 'code'),
                level=_atd_read_string(x['level']) if 'level' in x else _atd_missing_json_field('CliError', 'level'),
                type_=_atd_read_string(x['type']) if 'type' in x else _atd_missing_json_field('CliError', 'type'),
                rule_id=RuleId.from_json(x['rule_id']) if 'rule_id' in x else None,
                message=_atd_read_string(x['message']) if 'message' in x else None,
                path=Fpath.from_json(x['path']) if 'path' in x else None,
                long_msg=_atd_read_string(x['long_msg']) if 'long_msg' in x else None,
                short_msg=_atd_read_string(x['short_msg']) if 'short_msg' in x else None,
                spans=_atd_read_list(ErrorSpan.from_json)(x['spans']) if 'spans' in x else None,
                help=_atd_read_string(x['help']) if 'help' in x else None,
            )
        else:
            _atd_bad_json('CliError', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['code'] = _atd_write_int(self.code)
        res['level'] = _atd_write_string(self.level)
        res['type'] = _atd_write_string(self.type_)
        if self.rule_id is not None:
            res['rule_id'] = (lambda x: x.to_json())(self.rule_id)
        if self.message is not None:
            res['message'] = _atd_write_string(self.message)
        if self.path is not None:
            res['path'] = (lambda x: x.to_json())(self.path)
        if self.long_msg is not None:
            res['long_msg'] = _atd_write_string(self.long_msg)
        if self.short_msg is not None:
            res['short_msg'] = _atd_write_string(self.short_msg)
        if self.spans is not None:
            res['spans'] = _atd_write_list((lambda x: x.to_json()))(self.spans)
        if self.help is not None:
            res['help'] = _atd_write_string(self.help)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliError':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class CliOutput:
    """Original type: cli_output = { ... }"""

    errors: List[CliError]
    results: List[CliMatch]
    paths: CliPaths
    version: Optional[Version] = None
    time: Optional[CliTiming] = None
    explanations: Optional[List[MatchingExplanation]] = None
    rules_by_engine: Optional[List[RuleIdAndEngineKind]] = None
    engine_requested: Optional[EngineKind] = None

    @classmethod
    def from_json(cls, x: Any) -> 'CliOutput':
        if isinstance(x, dict):
            return cls(
                errors=_atd_read_list(CliError.from_json)(x['errors']) if 'errors' in x else _atd_missing_json_field('CliOutput', 'errors'),
                results=_atd_read_list(CliMatch.from_json)(x['results']) if 'results' in x else _atd_missing_json_field('CliOutput', 'results'),
                paths=CliPaths.from_json(x['paths']) if 'paths' in x else _atd_missing_json_field('CliOutput', 'paths'),
                version=Version.from_json(x['version']) if 'version' in x else None,
                time=CliTiming.from_json(x['time']) if 'time' in x else None,
                explanations=_atd_read_list(MatchingExplanation.from_json)(x['explanations']) if 'explanations' in x else None,
                rules_by_engine=_atd_read_list(RuleIdAndEngineKind.from_json)(x['rules_by_engine']) if 'rules_by_engine' in x else None,
                engine_requested=EngineKind.from_json(x['engine_requested']) if 'engine_requested' in x else None,
            )
        else:
            _atd_bad_json('CliOutput', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['errors'] = _atd_write_list((lambda x: x.to_json()))(self.errors)
        res['results'] = _atd_write_list((lambda x: x.to_json()))(self.results)
        res['paths'] = (lambda x: x.to_json())(self.paths)
        if self.version is not None:
            res['version'] = (lambda x: x.to_json())(self.version)
        if self.time is not None:
            res['time'] = (lambda x: x.to_json())(self.time)
        if self.explanations is not None:
            res['explanations'] = _atd_write_list((lambda x: x.to_json()))(self.explanations)
        if self.rules_by_engine is not None:
            res['rules_by_engine'] = _atd_write_list((lambda x: x.to_json()))(self.rules_by_engine)
        if self.engine_requested is not None:
            res['engine_requested'] = (lambda x: x.to_json())(self.engine_requested)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliOutput':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass(frozen=True)
class CliMatchTaintSource:
    """Original type: cli_match_taint_source = { ... }"""

    location: Location
    content: str

    @classmethod
    def from_json(cls, x: Any) -> 'CliMatchTaintSource':
        if isinstance(x, dict):
            return cls(
                location=Location.from_json(x['location']) if 'location' in x else _atd_missing_json_field('CliMatchTaintSource', 'location'),
                content=_atd_read_string(x['content']) if 'content' in x else _atd_missing_json_field('CliMatchTaintSource', 'content'),
            )
        else:
            _atd_bad_json('CliMatchTaintSource', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['location'] = (lambda x: x.to_json())(self.location)
        res['content'] = _atd_write_string(self.content)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'CliMatchTaintSource':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)


@dataclass
class ApiScansFindings:
    """Original type: api_scans_findings = { ... }"""

    findings: List[Finding]
    token: Optional[str]
    gitlab_token: Optional[str]
    searched_paths: List[str]
    rule_ids: List[str]

    @classmethod
    def from_json(cls, x: Any) -> 'ApiScansFindings':
        if isinstance(x, dict):
            return cls(
                findings=_atd_read_list(Finding.from_json)(x['findings']) if 'findings' in x else _atd_missing_json_field('ApiScansFindings', 'findings'),
                token=_atd_read_nullable(_atd_read_string)(x['token']) if 'token' in x else _atd_missing_json_field('ApiScansFindings', 'token'),
                gitlab_token=_atd_read_nullable(_atd_read_string)(x['gitlab_token']) if 'gitlab_token' in x else _atd_missing_json_field('ApiScansFindings', 'gitlab_token'),
                searched_paths=_atd_read_list(_atd_read_string)(x['searched_paths']) if 'searched_paths' in x else _atd_missing_json_field('ApiScansFindings', 'searched_paths'),
                rule_ids=_atd_read_list(_atd_read_string)(x['rule_ids']) if 'rule_ids' in x else _atd_missing_json_field('ApiScansFindings', 'rule_ids'),
            )
        else:
            _atd_bad_json('ApiScansFindings', x)

    def to_json(self) -> Any:
        res: Dict[str, Any] = {}
        res['findings'] = _atd_write_list((lambda x: x.to_json()))(self.findings)
        res['token'] = _atd_write_nullable(_atd_write_string)(self.token)
        res['gitlab_token'] = _atd_write_nullable(_atd_write_string)(self.gitlab_token)
        res['searched_paths'] = _atd_write_list(_atd_write_string)(self.searched_paths)
        res['rule_ids'] = _atd_write_list(_atd_write_string)(self.rule_ids)
        return res

    @classmethod
    def from_json_string(cls, x: str) -> 'ApiScansFindings':
        return cls.from_json(json.loads(x))

    def to_json_string(self, **kw: Any) -> str:
        return json.dumps(self.to_json(), **kw)
