Json.net 如何无序地编写JSON——可能是多个编写器,如果是,如何编写?

Json.net 如何无序地编写JSON——可能是多个编写器,如果是,如何编写?,json.net,Json.net,以下是我的设想: 我正在展平并序列化一个对象图。最终的结果是,我将把每种类型的所有对象收集到该类型的数组中,并对每种类型序列化一个数组。但是我需要在遍历对象图时进行序列化(遍历规则很复杂,需要反射来读取属性——因此图形的多次遍历是非常不可取的——我想使用JSON.Net的遍历,以便其属性也可以用于控制遍历) 因此,假设我有TypeA对象和TypeB对象,假设TypeA对象可以有TypeB类型的属性,而TypeB对象可以有TypeA类型的属性(不一定是对等的!)。假设我的对象图如下所示: Type

以下是我的设想:

我正在展平并序列化一个对象图。最终的结果是,我将把每种类型的所有对象收集到该类型的数组中,并对每种类型序列化一个数组。但是我需要在遍历对象图时进行序列化(遍历规则很复杂,需要反射来读取属性——因此图形的多次遍历是非常不可取的——我想使用JSON.Net的遍历,以便其属性也可以用于控制遍历)

因此,假设我有
TypeA
对象和
TypeB
对象,假设
TypeA
对象可以有
TypeB
类型的属性,而
TypeB
对象可以有
TypeA
类型的属性(不一定是对等的!)。假设我的对象图如下所示:

TypeA aInst1 = new TypeA {
    Id = 1,
    MyB = new TypeB {
        Id = 101,
        MyA = new TypeA {
             Id = 2,
             MyB = null
        }
    }
}
我想要的结果是:

{
    typeAs: [
        {
            id: 1,
            myB: 101
        },
        {
            id: 2,
            myB: null
        }
    ],
    typeBs: [
        {
            id: 101,
            myA: 2
        }
    ]
}
这里的关键是:当我序列化TypeAs(比如说,使用
TypeAConverter
)时,我会将必要的TypeB对象添加到TypeB哈希集中,以确保它们被序列化(很简单)——但在遍历TypeB时,我需要做相反的事情——但是如果我线性地这样做,我将已经序列化了TypeAs,并且不能向后跳转以添加新发现的对象

现在,我已经知道我必须处理很多事情(遍历深度、多次遍历、获取对根对象的引用以首先到达TypeXs哈希集),其中大部分我认为我已经解决了

我不确定如何处理序列化的无序性。到目前为止,我的计划是为每种类型启动多个
JsonWriters
,然后使用
WriteRaw
将它们的输出附加到主文档/编写器。但要做到这一点,我必须将自己的范围缩小到
JsonTextWriter
,因为更抽象的
JsonWriter
类似乎没有访问序列化输出的方法。例如,我不想限制我的用户使用
BsonWriter
(如果这是一个实际的目标……似乎是这样)

顺便说一句,我并没有提出这种格式,我只是试图实现它——尽可能用一种通用的方式

编辑
对于一些其他背景,我已经声明了一个接口(称为
IModel
),用户将使用该接口“标记”可由该序列化库专门处理的任何类--有一个
ModelConverter
,它捕获任何
IModel
实例以应用这些特殊规则。我还有一个根对象(class
Payload
),用户必须使用它来放入IModel(并设置一些可选配置)。
Payload
对象跟踪
TypeXs
数组(确切地说是在
字典中),我有一个
公共静态字典
,它可以进行备份(使用
模型转换器可用的
序列化程序.Context
),因此,这就是我能够在事后返回并添加这些对象的方式。

无论如何,我使用多个
JsonTextWriter
s(每种类型一个)的计划奏效了,尽管这有点笨拙,我还是希望找到一种不将我锁定在一个
JsonWriter
实现中的方法

这是我实现的核心…显然,整个解决方案涉及两个
jsonconverter
和其他几个类,但这是我创建、跟踪和使用每类型
JsonTextWriter
的部分:

//处理附录
/*这有点混乱,因为我们可能会将给定类型的项添加到
*我们目前正在处理的集合。这不仅是一个问题,因为你
*无法在枚举集合时修改集合(因此我们要创建一个
*首先复制),但我们需要捕获新添加的对象和进程
*他们也是。所以,我们必须一直传球,直到我们发现为止
*我们没有在任何附录中添加任何新对象。
*/
字典
已处理=新字典(),
toBeProcessed=新字典();//这真的有必要吗?
/*除此之外,每个附录都需要一个新的JsonWriter——因为
*可以写入类型A的对象,然后在处理类型B时发现
*我们需要写更多的A类对象!所以我们不能继续追加
*给同一位作家。
*/
/*哦,我们必须保留对JsonWriter的TextWriter的引用
*因为没有会员可以再把它拿出来?!?
* */
词典编写者=新词典();
国际条约;
做
{
numadeditions=0;
foreach(有效载荷中的密钥值对。附录)
{
Type=apair.Key;
ISet附录=平均值;
jw;
if(writers.ContainsKey(类型))
{
jw=writers[type].Key;
}
其他的
{
//设置并启动此类型的写入程序。。。
StringWriter sw=新的StringWriter();
jw=新的JsonTextWriter(sw);
writers[type]=新的KeyValuePair(jw,sw);
jw.writestarray();
}
HashSet-tbp;
if(已处理。容器(类型))
{
toBeProcessed[type]=tbp=新哈希集(附录。除(processed[type]));
}
其他的
{
toBeProcessed[type]=tbp=新哈希集(附录);
已处理的[type]=新哈希集();
}
如果(待定计数>0)
{
NumAditions+=待处理计数;
foreach(tbp中的对象对象对象)
{
serializer.Serialize(jw,obj);//注意,不是writer,而是jw——我们将每种类型写入它自己的JsonWriter中,然后将它们组合起来。
}
已处理[类型]。与(tbp)合并;
}
//TODO:添加遍历深度限制器!
}
}而(数值条件>0);
如果(有效载荷.附录.计数>0)
{
writer.writeproperty