MonoGame - 通过内容管道加载JSON

问题描述 投票:1回答:1

我正在创建一个RPG游戏,我需要用Tiled加载地图。我把Tiled部分放下(我正在使用MonoGame.Extended)。但我需要有关地图的额外数据。我的计划是使用包含必要信息的JSON文件。但是,我想通过内容管道获取它,因为它与tile贴图直接相关。

我试图使用自定义内容管道扩展。它使用JSON.Net将JSON文件反序列化为Dictionary<string, dynamic>。但是,当我编译DLL文件并尝试将其引用到管道工具时,管道工具将始终崩溃。

内容导入者:

using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework.Content.Pipeline;

using Newtonsoft.Json;

namespace JsonExtension
{

    [ContentImporter(".json", DefaultProcessor = "JsonProcessor")]
    public class JsonImporter : ContentImporter<Dictionary<string, dynamic>>
    {

        public override Dictionary<string, dynamic> Import(string filename, ContentImporterContext context)
        {
            context.Logger.LogMessage("Importing JSON file: {0}", filename);

            using (var streamReader = new StreamReader(filename))
            {
                JsonSerializer serializer = new JsonSerializer();
                return (Dictionary<string, dynamic>)serializer.Deserialize(streamReader, typeof(Dictionary<string, dynamic>));
            }
        }

    }

}

内容处理器:

using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework.Content.Pipeline;

namespace JsonExtension
{
    [ContentProcessor]
    public class JsonProcessor : ContentProcessor<Dictionary<string, dynamic>, Dictionary<string, dynamic>>
    {
        public override Dictionary<string, dynamic> Process(Dictionary<string, dynamic> input, ContentProcessorContext context)
        {
            context.Logger.LogMessage("Processing JSON");

            return input;
        }
    }
}

内容类型作者:

using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;

using Newtonsoft.Json;

namespace JsonExtension
{
    [ContentTypeWriter]
    class JsonTypeWriter : ContentTypeWriter<Dictionary<string, dynamic>>
    {
        protected override void Write(ContentWriter output, Dictionary<string, dynamic> value)
        {
            output.Write(JsonConvert.SerializeObject(value));
        }

        public override string GetRuntimeType(TargetPlatform targetPlatform)
        {
            return typeof(Dictionary<string, dynamic>).AssemblyQualifiedName;
        }

        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
            return "JsonExtension.JsonReader";
        }
    }
}

有没有更好的方法来存储Tiled地图元数据?或者有更好的方法通过管道导入它?或者我的内容导入器出了什么问题?

c# json monogame
1个回答
1
投票

该错误是由于dynamic类型。管道要求所有类型都可以通过Reflection进行解析和实例化。

Generic集合有一个辅助解析器,用于序列化和反序列化Generic中的每个类型。线Dictionary<string, dynamic>有两种类型和不可知的类型相关System.Collections.Generic.DictionarySystem.Stringdynamicdynamic没有关于使用什么类型的提示,也无法解决导致错误。

简单的解决方案是将数据存储为json String(除了您尝试将其存储的类型为dynamic之外,您现在已经在执行此操作)并在String返回数据后将Content.Load反序列化为其对象。

换句话说,使用Dictionary<string, string>作为内容处理器类型。


更简单的解决方案是将JSON文件复制到输出目录。构建动作“如果更新则复制”并使用System.IO.File读取它,并使用JSON.NET将其反序列化为Game1的Initialize方法中的对象。

© www.soinside.com 2019 - 2024. All rights reserved.