5

In my ASP.NET MVC Web project, I have got a number of JSON files lying around.

File1.json

{
   "manage_employees_section_title": 
    {
        "value": "Manage employees",
        "description": "The mange employees section title"
    }
}

File2.json

{
   "manage_operations_section_title": 
    {
        "value": "Manage operations
        "description": "The mange operations section title"
    }
}

I need to as part of my build process get all my JSONs and merge into one single file.

I have used MSBuild like this.

<Target Name="ConcatenateJsFiles">
   <ItemGroup>
     <ConcatFiles Include="Application\**\resource-content*.json"/>
   </ItemGroup>

   <ReadLinesFromFile File="%(ConcatFiles.Identity)">
     <Output TaskParameter="Lines" ItemName="ConcatLines"/>
   </ReadLinesFromFile>

   <WriteLinesToFile File="Infrastructure\Content\Store\ContentStore.json" Lines="@(ConcatLines)" Overwrite="true" />
</Target>

And this is what I got...

Concat.json

//What I got
{
   "manage_employees_section_title": 
    {
        "value": "Manage employees",
        "description": "The mange employees section title"
    }
}
{
   "manage_operations_section_title": 
    {
        "value": "Manage operations
        "description": "The mange operations section title"
    }
}

Even though I have achieved my goal of concatenation, what I really want is to merge all JSON files into one JSON object.

//What I really want
{
   "manage_employees_section_title": 
    {
        "value": "Manage employees",
        "description": "The mange employees section title"
    },
   "manage_operations_section_title": 
    {
        "value": "Manage operations
        "description": "The mange operations section title"
    }
}

How can I achieve this as part of my build process with Visual Studio.

Many thanks in advance guys..

1
  • Though not the answer to this question exactly, I ended up manipulating the result at runtime like this : stackoverflow.com/a/29015370/502130 Commented Mar 12, 2015 at 17:09

2 Answers 2

3

It was interesting task to obtain the result using MSBuild functionality only... To be honest, creating additional C# application for this goal is better approach. But I was able to do it with MSBuild as well:

<Project ToolsVersion="12.0" DefaultTargets="ConcatenateJsFiles" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
  <Target Name="ConcatenateJsFiles">
    <ItemGroup>
      <ConcatFiles Include="Application\**\resource-content*.json"/>
    </ItemGroup>

    <ItemGroup>
      <!-- Read file content (with spaces preserving), remove trailing { and } -->
      <ContentLines Include="$([System.IO.File]::ReadAllText('%(ConcatFiles.Identity)').Remove($([MSBuild]::Subtract($([System.IO.File]::ReadAllText('%(ConcatFiles.Identity)').Length), 1)), 1).Remove(0, 1))"/>
      <!-- Create resulting file with trailing { and } -->
      <FileContent Include="{"/>
      <FileContent Include="@(ContentLines, ',%0a')"/>
      <FileContent Include="}"/>
    </ItemGroup>

    <WriteLinesToFile File="ContentStore.json" Lines="@(FileContent)" Overwrite="true" />
  </Target>
</Project>

As a result you'll have the following file:

{
"manage_employees_section_title": 
    {
        "value": "Manage employees",
        "description": "The mange employees section title"
    },
"manage_operations_section_title": 
    {
        "value": "Manage operations",
        "description": "The mange operations section title"
    }
}

This approach is not flexible enough, for example it requires trailing braces to be located at the first and at the last positions of source files. Anyway, it is enough to demonstrate how to do it with MBSuild only.

Sign up to request clarification or add additional context in comments.

Comments

0

One thing you can do is create a small C# application and add that to your pre-build process:

Create an application that takes an argument for a directory. You can use the .NET JSON parsing classes in the System.Runtime.Serialization.DataContractJsonSerializer to get objects from each of your JSON files. Based on your description, it sounds like you can already parse the objects successfully.

Put all of the objects into a collection and serialize the output into a single file. When running multiple instances of VS you may run into problems with file access, so name your file uniquely.

Add your application to the Properties > Build Events > Pre-build Event Command Line in visual studio. You can determine the working directory at build time using some of the build macros included in visual studio. For example, MyApp.exe $(ProjectDir) would pass the argument of the project directory, which would be decided at build time should you have multiple areas.

-MF

1 Comment

I agree with the logic, but I would make a custom MSBuild task.... toe-may-toes...toe-matt-toes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.