# Abstract Types and StructTypes - error reading AbstractTypes into concrete with JSON3

**URL:** https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897
**Category:** General Usage
**Tags:** question, package, json3, structtypes
**Created:** [May 10, 2021, 3:16pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897 "2021-05-10T15:16:50Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![djholiver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djholiver/32/50470_2.png) [@djholiver](https://discourse.julialang.org/u/djholiver)
#### Post date: [May 10, 2021, 3:16pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/1 "2021-05-10T15:16:50Z")

</div>

Hi,

Believe I am running into a bit of a bug / unexpected behaviour that I can’t seem to work around when extracting an interface into a concrete type having defined more than one in a module.

e.g.: this works:

```julia

using StructTypes, Parameters, JSON3
abstract type ICompute end
StructTypes.StructType(::Type{ICompute}) = StructTypes.AbstractType()
StructTypes.subtypekey(::Type{ICompute}) = :computeName
function StructTypes.subtypes(::Type{ICompute})
(
    percentile = Percentile
)
end

struct Percentile <: ICompute
    computeName
    id
    percentiles :: Vector{Float64}
end
StructTypes.StructType(::Type{Percentile}) = StructTypes.Struct()

percentile = JSON3.read("""
{
    "computeName": "percentile",
    "id": "1",
    "percentiles": [10,20,30]
    }""", ICompute)

```

works, but trying to extend it to include more abstract types:

```julia
using StructTypes, Parameters, JSON3
abstract type ICompute end
StructTypes.StructType(::Type{ICompute}) = StructTypes.AbstractType()
StructTypes.subtypekey(::Type{ICompute}) = :computeName
function StructTypes.subtypes(::Type{ICompute})
(
    percentile = Percentile
)
end

struct Percentile <: ICompute
    computeName
    id
    percentiles :: Vector{Float64}
end
StructTypes.StructType(::Type{Percentile}) = StructTypes.Struct()

abstract type IQuery end
StructTypes.StructType(::Type{IQuery}) = StructTypes.AbstractType()
StructTypes.subtypekey(::Type{IQuery}) = :queryName
function StructTypes.subtypes(::Type{IQuery})
(
    dataDominance = DataDominance
)
end

struct DataDominance <: IQuery
    queryName
    id
    percentiles :: Vector{Float64}
end
StructTypes.StructType(::Type{DataDominance}) = StructTypes.Struct()

percentile = JSON3.read("""
{
    "computeName": "percentile",
    "id": "1",
    "percentiles": [10,20,30]
    }""", ICompute)

datadominance = JSON3.read("""
{
    "queryName": "dataDominance",
    "id": "1",
    "percentiles": [10,20,30]
    }""", IQuery)

```

fails with error:

```julia
ERROR: LoadError: MethodError: no method matching length(::Type{Main.GetMetricModels.DataDominance})
Closest candidates are:
  length(!Matched::Union{Base.KeySet, Base.ValueIterator}) at abstractdict.jl:58
  length(!Matched::Union{LinearAlgebra.Adjoint{T, S}, LinearAlgebra.Transpose{T, S}} where {T, S}) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\LinearAlgebra\src\adjtrans.jl:195
  length(!Matched::Union{DataStructures.OrderedRobinDict, DataStructures.RobinDict}) at C:\Users\doliver\.julia\packages\DataStructures\ixwFs\src\ordered_robin_dict.jl:86

```

version info:

![image](https://global.discourse-cdn.com/julialang/original/3X/3/2/32df4ba9b0c7556bd8cfcce3012e04b793503eb6.png)

Packages info:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/0/e/0e78d4643586f296994fa2cd3b3e3f0e55e1a8f6.png)

Would someone mind trying to run the above and feeding back - I’ve tried myriad combinations and just not been successful.

Regards,

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [May 10, 2021, 5:35pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/2 "2021-05-10T17:35:07Z")

</div>

I could not run your code (`Average not defined`). It is a little bit odd to me the concept of writing and reading abstract types from a JSON file (how to know what the structure of the data written?) but I may be not aware of how that works.

Anyway, if you could provide a MWE, that will help.

---

<div class="post-metadata">

### Author: ![djholiver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djholiver/32/50470_2.png) [@djholiver](https://discourse.julialang.org/u/djholiver)
#### Post date: [May 10, 2021, 6:34pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/3 "2021-05-10T18:34:07Z")

</div>

Hi - thanks for responding - updated the above - I hadn’t removed the other subtypes from the listing.

As to the usage - it’s supported by [Structypes.jl](https://juliadata.github.io/StructTypes.jl/stable/) and I make use of it to facilitate multiple dispatch of computations (and filters) provided by users to an http endpoint on top of a calculation library.

i.e. Percentiles require percentile arguments but Average / Sum wouldn’t but they are both of type “ICompute”. The above snippet was / is working fine until I introduced “IQuery”, resulting in the error thrown.

Incidentally - I saw your contribution [here](https://discourse.julialang.org/t/how-do-i-make-a-dispatch-table-using-multiple-dispatch-instead-of-dict/60784/21) and this StructTypes + Interface approach would potentially be applicable (I would post it if it worked…), since the OP is essentially making use of properties of a type rather than the type, with a default required for the generic: implying a conversion step on raw data (JSON?) to a type (or not) and an implementation of that method for the converted type to support multiple dispatch.

Like this:

```julia
#support calcs that allow streaming:
#default - fall through
streamingUpdate!(compute:: ICompute, value) = ()

function streamingUpdate!(ave:: Average, value) 
    
    if(ismissing(value)) return end
    ave.runningTotal += value
    ave.runningCount += 1

end

function streamingUpdate!(sum:: Sum, value) 
    
    if(ismissing(value)) return end
    sum.runningTotal += value

end

```

Regards,

---

<div class="post-metadata">

### Author: ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)
#### Post date: [May 10, 2021, 7:06pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/4 "2021-05-10T19:06:29Z")

</div>

Maybe you need

> `StructTypes.subtypekey` that indicates which input key/field name should be used for identifying the appropriate concrete subtype.

defining “queryName” and “computeName”?

---

<div class="post-metadata">

### Author: ![djholiver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djholiver/32/50470_2.png) [@djholiver](https://discourse.julialang.org/u/djholiver)
#### Post date: [May 10, 2021, 9:27pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/5 "2021-05-10T21:27:14Z")

</div>

Thanks - unfortunately not as simple - I already define this in the script above

Regards

---

<div class="post-metadata">

### Author: ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)
#### Post date: [May 10, 2021, 9:29pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/6 "2021-05-10T21:29:09Z")

</div>

Sorry, I didn’t notice it.

---

<div class="post-metadata">

### Author: ![djholiver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djholiver/32/50470_2.png) [@djholiver](https://discourse.julialang.org/u/djholiver)
#### Post date: [May 11, 2021, 5:20pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/7 "2021-05-11T17:20:14Z")

</div>

No problem at all.

would you be able to see if the original code snippets run for you? Still at a loss whats going on.

@lmiq did the edits allow you to execute the snippets?

Regards

---

<div class="post-metadata">

### Author: ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)
#### Post date: [May 11, 2021, 5:32pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/8 "2021-05-11T17:32:58Z")

</div>

Both snippets fail for me with:

```julia
ERROR: LoadError: MethodError: no method matching length(::Type{Percentile})
Closest candidates are:
  length(::Union{Base.KeySet, Base.ValueIterator}) at abstractdict.jl:58
  length(::Union{LinearAlgebra.Adjoint{T, S}, LinearAlgebra.Transpose{T, S}} where {T, S}) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\LinearAlgebra\src\adjtrans.jl:195
  length(::Base.LogicalIndex) at multidimensional.jl:732
  ...

```

My versioninfo() is the same as your except minor hardware details.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [May 11, 2021, 5:51pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/9 "2021-05-11T17:51:04Z")

</div>

> [@djholiver](#):
>
> @leandromartinez98 did the edits allow you to execute the snippets?

Yes, but I don’t know how to solve the problem ☹

---

<div class="post-metadata">

### Author: ![djholiver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djholiver/32/50470_2.png) [@djholiver](https://discourse.julialang.org/u/djholiver)
#### Post date: [May 11, 2021, 6:44pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/10 "2021-05-11T18:44:28Z")

</div>

Many thanks to you both for trying - very odd that it works for @lmiq across both snippets but not for @Jeff_Emanuel at all…

Must be down to package and / or Julia versions - I can still get one scenario to work!

I’ll revert if I find the solution / issue.

Regards,

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [May 11, 2021, 6:47pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/11 "2021-05-11T18:47:54Z")

</div>

Oh, no, I meant that I can run the code, not that it works. I doesn’t work (I get the same error as you).

---

<div class="post-metadata">

### Author: ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)
#### Post date: [May 11, 2021, 7:41pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/12 "2021-05-11T19:41:16Z")

</div>

It should be

```julia
function StructTypes.subtypes(::Type{ICompute})
(
    percentile = Percentile,
)
end

```

---

<div class="post-metadata">

### Author: ![djholiver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djholiver/32/50470_2.png) [@djholiver](https://discourse.julialang.org/u/djholiver)
#### Post date: [May 11, 2021, 8:07pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/13 "2021-05-11T20:07:08Z")

</div>

Thanks @Skoffer ! I was hoping it was something simple - very counter intuitive - is it something to do with Tuple definitions?

Thanks all for contributing.

Regards

---

<div class="post-metadata">

### Author: ![lhnguyen-vn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lhnguyen-vn/32/15449_2.png) [@lhnguyen-vn](https://discourse.julialang.org/u/lhnguyen-vn)
#### Post date: [May 11, 2021, 10:58pm UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/14 "2021-05-11T22:58:35Z")

</div>

Parentheses are also used to specify order of operations, so an explicit comma is required to disambiguate that you’re constructing a tuple.

---

<div class="post-metadata">

### Author: ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)
#### Post date: [May 12, 2021, 9:30am UTC](https://discourse.julialang.org/t/abstract-types-and-structtypes-error-reading-abstracttypes-into-concrete-with-json3/60897/15 "2021-05-12T09:30:07Z")

</div>

The way how it is written is slightly confusing, since tabs do not correspond to usual notations. If you rewrite your original code as

```julia
function StructTypes.subtypes(::Type{ICompute}) 
    (percentile = Percentile)
end

```

Or even better

```julia
StructTypes.subtypes(::Type{ICompute}) = (percentile = Percentile)

```

then issue is more obvious. In expression `(percentile = Percentile)` brackets are ignored, so it is equivalent to `percentile = Percentile`, i.e. it creates throaway variable `percentile` and returns the result of assignment operator which is equals to `Percentile`. So, instead of returning `NamedTuple` function was equivalent to

```julia
StructTypes.subtypes(::Type{ICompute}) = Percentile

```

And of course, since type is not the same as `NamedTuple` `StructTypes` was unable to process it.

If you want to create named tuple with single field, you can either use comma after expression or semicolon at the beginning. So both will do

```julia
StructTypes.subtypes(::Type{ICompute}) = (percentile = Percentile, )
# or
StructTypes.subtypes(::Type{ICompute}) = (; percentile = Percentile)

```
