diff --git a/DynamicModel.cc b/DynamicModel.cc
index 08dd2bc4572f89d5a8e5aa4f2793b1f0e9b96c59..704592dabdf9ea18a255727c46487d06e9f4bf9a 100644
--- a/DynamicModel.cc
+++ b/DynamicModel.cc
@@ -5336,3 +5336,10 @@ DynamicModel::writeCCOutput(ostream &output, const string &basename, bool block_
     output << "NNZDerivatives.push_back(-1);" << endl
            << "NNZDerivatives.push_back(-1);" << endl;
 }
+
+
+void
+DynamicModel::writeJsonOutput(ostream &output) const
+{
+  writeJsonModelEquations(output);
+}
diff --git a/DynamicModel.hh b/DynamicModel.hh
index 6b99423c705da7b71e4944a1a8792c82a4878e00..e79ac7f4271389ef9ba57ebc96c2304c25665058 100644
--- a/DynamicModel.hh
+++ b/DynamicModel.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2016 Dynare Team
+ * Copyright (C) 2003-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -217,6 +217,9 @@ public:
   //! Writes model initialization and lead/lag incidence matrix to output
   void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const;
 
+  //! Write JSON Output
+  void writeJsonOutput(ostream &output) const;
+
   //! Return true if the hessian is equal to zero
   inline bool checkHessianZero() const;
 
diff --git a/DynareMain.cc b/DynareMain.cc
index adbb1b6821f2afdcc799949a6f99d16d1699406a..c56509262bd83a287f535ff41045cbcb6321d45b 100644
--- a/DynareMain.cc
+++ b/DynareMain.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2016 Dynare Team
+ * Copyright (C) 2003-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -45,6 +45,7 @@ void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
            , bool cygwin, bool msvc, bool mingw
 #endif
+           , bool json, JsonFileOutputType json_output_mode
            );
 
 void main1(char *modfile, string &basename, bool debug, bool save_macro, string &save_macro_file,
@@ -61,6 +62,7 @@ usage()
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
        << " [cygwin] [msvc] [mingw]"
 #endif
+       << "[json] [jsonstdout]"
        << endl;
   exit(EXIT_FAILURE);
 }
@@ -113,6 +115,8 @@ main(int argc, char **argv)
   map<string, string> defines;
   vector<string> path;
   FileOutputType output_mode = none;
+  bool json = false;
+  JsonFileOutputType json_output_mode = file;
   LanguageOutputType language = matlab;
 
   // Parse options
@@ -291,6 +295,10 @@ main(int argc, char **argv)
                 }
             }
         }
+      else if (!strcmp(argv[arg], "jsonstdout"))
+        json_output_mode = standardout;
+      else if (!strcmp(argv[arg], "json"))
+        json = true;
       else
         {
           cerr << "Unknown option: " << argv[arg] << endl;
@@ -337,6 +345,7 @@ main(int argc, char **argv)
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
         , cygwin, msvc, mingw
 #endif
+        , json, json_output_mode
         );
 
   return EXIT_SUCCESS;
diff --git a/DynareMain2.cc b/DynareMain2.cc
index bc5065b2d2c44f3957b415e81e530f61f6677d87..3bbc4b4fdd584ac417abef396f5c19104cce7dbf 100644
--- a/DynareMain2.cc
+++ b/DynareMain2.cc
@@ -34,12 +34,20 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
       , bool cygwin, bool msvc, bool mingw
 #endif
+      , bool json, JsonFileOutputType json_output_mode
       )
 {
   ParsingDriver p(warnings, nostrict);
 
   // Do parsing and construct internal representation of mod file
   ModFile *mod_file = p.parse(in, debug);
+  if (json)
+    {
+      mod_file->symbol_table.freeze();
+      mod_file->writeJsonOutput(basename, json_output_mode);
+      mod_file->symbol_table.unfreeze();
+      cout << "JSON file written after Parsing step." << endl;
+    }
 
   // Run checking pass
   mod_file->checkPass(nostrict);
diff --git a/ExprNode.cc b/ExprNode.cc
index d7d8374c5b832bd7712863be6e678d13e91afa03..ccba75c2834488580e9b2072af6635411e8c0c4b 100644
--- a/ExprNode.cc
+++ b/ExprNode.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2016 Dynare Team
+ * Copyright (C) 2007-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -322,6 +322,14 @@ NumConstNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
     output << datatree.num_constants.get(id);
 }
 
+void
+NumConstNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                              const temporary_terms_t &temporary_terms,
+                              deriv_node_temp_terms_t &tef_terms) const
+{
+  output << datatree.num_constants.get(id);
+}
+
 bool
 NumConstNode::containsExternalFunction() const
 {
@@ -615,6 +623,16 @@ VariableNode::containsExternalFunction() const
   return false;
 }
 
+void
+VariableNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                              const temporary_terms_t &temporary_terms,
+                              deriv_node_temp_terms_t &tef_terms) const
+{
+  output << datatree.symbol_table.getName(symb_id);
+  if (lag != 0)
+    output << "(" << lag << ")";
+}
+
 void
 VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
                           const temporary_terms_t &temporary_terms,
@@ -1850,6 +1868,141 @@ UnaryOpNode::containsExternalFunction() const
   return arg->containsExternalFunction();
 }
 
+void
+UnaryOpNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                             const temporary_terms_t &temporary_terms,
+                             deriv_node_temp_terms_t &tef_terms) const
+{
+  // Always put parenthesis around uminus nodes
+  if (op_code == oUminus)
+    output << LEFT_PAR(output_type);
+
+  switch (op_code)
+    {
+    case oUminus:
+      output << "-";
+      break;
+    case oExp:
+      output << "exp";
+      break;
+    case oLog:
+      output << "log";
+      break;
+    case oLog10:
+      output << "log10";
+      break;
+    case oCos:
+      output << "cos";
+      break;
+    case oSin:
+      output << "sin";
+      break;
+    case oTan:
+      output << "tan";
+      break;
+    case oAcos:
+      output << "acos";
+      break;
+    case oAsin:
+      output << "asin";
+      break;
+    case oAtan:
+      output << "atan";
+      break;
+    case oCosh:
+      output << "cosh";
+      break;
+    case oSinh:
+      output << "sinh";
+      break;
+    case oTanh:
+      output << "tanh";
+      break;
+    case oAcosh:
+      output << "acosh";
+      break;
+    case oAsinh:
+      output << "asinh";
+      break;
+    case oAtanh:
+      output << "atanh";
+      break;
+    case oSqrt:
+      output << "sqrt";
+      break;
+    case oAbs:
+      output << "abs";
+      break;
+    case oSign:
+      output << "sign";
+      break;
+    case oSteadyState:
+      output << "(";
+      arg->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+      output << ")";
+      return;
+    case oSteadyStateParamDeriv:
+      {
+        VariableNode *varg = dynamic_cast<VariableNode *>(arg);
+        assert(varg != NULL);
+        assert(datatree.symbol_table.getType(varg->symb_id) == eEndogenous);
+        assert(datatree.symbol_table.getType(param1_symb_id) == eParameter);
+        int tsid_endo = datatree.symbol_table.getTypeSpecificID(varg->symb_id);
+        int tsid_param = datatree.symbol_table.getTypeSpecificID(param1_symb_id);
+        assert(IS_MATLAB(output_type));
+        output << "ss_param_deriv(" << tsid_endo+1 << "," << tsid_param+1 << ")";
+      }
+      return;
+    case oSteadyStateParam2ndDeriv:
+      {
+        VariableNode *varg = dynamic_cast<VariableNode *>(arg);
+        assert(varg != NULL);
+        assert(datatree.symbol_table.getType(varg->symb_id) == eEndogenous);
+        assert(datatree.symbol_table.getType(param1_symb_id) == eParameter);
+        assert(datatree.symbol_table.getType(param2_symb_id) == eParameter);
+        int tsid_endo = datatree.symbol_table.getTypeSpecificID(varg->symb_id);
+        int tsid_param1 = datatree.symbol_table.getTypeSpecificID(param1_symb_id);
+        int tsid_param2 = datatree.symbol_table.getTypeSpecificID(param2_symb_id);
+        assert(IS_MATLAB(output_type));
+        output << "ss_param_2nd_deriv(" << tsid_endo+1 << "," << tsid_param1+1
+               << "," << tsid_param2+1 << ")";
+      }
+      return;
+    case oExpectation:
+      output << "EXPECTATION(" << expectation_information_set << ")";
+      break;
+    case oErf:
+      output << "erf";
+      break;
+    }
+
+    bool close_parenthesis = false;
+
+  /* Enclose argument with parentheses if:
+     - current opcode is not uminus, or
+     - current opcode is uminus and argument has lowest precedence
+  */
+  if (op_code != oUminus
+      || (op_code == oUminus
+          && arg->precedence(output_type, temporary_terms) < precedence(output_type, temporary_terms)))
+    {
+      output << LEFT_PAR(output_type);
+      if (op_code == oSign && (output_type == oCDynamicModel || output_type == oCStaticModel))
+        output << "1.0,";
+      close_parenthesis = true;
+    }
+
+  // Write argument
+  arg->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+
+  if (close_parenthesis)
+    output << RIGHT_PAR(output_type);
+
+  // Close parenthesis for uminus
+  if (op_code == oUminus)
+    output << RIGHT_PAR(output_type);
+}
+
 void
 UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
                          const temporary_terms_t &temporary_terms,
@@ -3072,6 +3225,119 @@ BinaryOpNode::containsExternalFunction() const
     || arg2->containsExternalFunction();
 }
 
+void
+BinaryOpNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                              const temporary_terms_t &temporary_terms,
+                              deriv_node_temp_terms_t &tef_terms) const
+{
+  if (op_code == oMax || op_code == oMin)
+    {
+      switch (op_code)
+        {
+        case oMax:
+          output << "max(";
+          break;
+        case oMin:
+          output << "min(";
+          break;
+        default:
+          ;
+        }
+      arg1->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+      output << ",";
+      arg2->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+      output << ")";
+      return;
+    }
+
+  int prec = precedence(output_type, temporary_terms);
+
+  bool close_parenthesis = false;
+
+  // If left argument has a lower precedence, or if current and left argument are both power operators,
+  // add parenthesis around left argument
+  BinaryOpNode *barg1 = dynamic_cast<BinaryOpNode *>(arg1);
+  if (arg1->precedence(output_type, temporary_terms) < prec
+      || (op_code == oPower && barg1 != NULL && barg1->op_code == oPower))
+    {
+      output << LEFT_PAR(output_type);
+      close_parenthesis = true;
+    }
+
+  // Write left argument
+  arg1->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+
+  if (close_parenthesis)
+    output << RIGHT_PAR(output_type);
+
+  // Write current operator symbol
+  switch (op_code)
+    {
+    case oPlus:
+      output << "+";
+      break;
+    case oMinus:
+      output << "-";
+      break;
+    case oTimes:
+      output << "*";
+      break;
+    case oDivide:
+      output << "/";
+      break;
+    case oPower:
+      output << "^";
+      break;
+    case oLess:
+      output << "<";
+      break;
+    case oGreater:
+      output << ">";
+      break;
+    case oLessEqual:
+      output << "<=";
+      break;
+    case oGreaterEqual:
+      output << ">=";
+      break;
+    case oEqualEqual:
+      output << "==";
+      break;
+    case oDifferent:
+      output << "!=";
+      break;
+    case oEqual:
+      output << "=";
+      break;
+    default:
+      ;
+    }
+
+  close_parenthesis = false;
+
+  /* Add parenthesis around right argument if:
+     - its precedence is lower than those of the current node
+     - it is a power operator and current operator is also a power operator
+     - it is a minus operator with same precedence than current operator
+     - it is a divide operator with same precedence than current operator */
+  BinaryOpNode *barg2 = dynamic_cast<BinaryOpNode *>(arg2);
+  int arg2_prec = arg2->precedence(output_type, temporary_terms);
+  if (arg2_prec < prec
+      || (op_code == oPower && barg2 != NULL && barg2->op_code == oPower && !IS_LATEX(output_type))
+      || (op_code == oMinus && arg2_prec == prec)
+      || (op_code == oDivide && arg2_prec == prec && !IS_LATEX(output_type)))
+    {
+      output << LEFT_PAR(output_type);
+      close_parenthesis = true;
+    }
+
+  // Write right argument
+  arg2->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+
+  if (close_parenthesis)
+    output << RIGHT_PAR(output_type);
+}
+
 void
 BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
                           const temporary_terms_t &temporary_terms,
@@ -4211,6 +4477,29 @@ TrinaryOpNode::containsExternalFunction() const
     || arg3->containsExternalFunction();
 }
 
+void
+TrinaryOpNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                               const temporary_terms_t &temporary_terms,
+                               deriv_node_temp_terms_t &tef_terms) const
+{
+  switch (op_code)
+    {
+    case oNormcdf:
+      output << "normcdf(";
+      break;
+    case oNormpdf:
+      output << "normpdf(";
+      break;
+    }
+
+  arg1->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+  output << ",";
+  arg2->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+  output << ",";
+  arg3->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+  output << ")";
+}
+
 void
 TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
                            const temporary_terms_t &temporary_terms,
@@ -4891,6 +5180,21 @@ AbstractExternalFunctionNode::writeExternalFunctionArguments(ostream &output, Ex
     }
 }
 
+void
+AbstractExternalFunctionNode::writeJsonExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type,
+                                                                 const temporary_terms_t &temporary_terms,
+                                                                 deriv_node_temp_terms_t &tef_terms) const
+{
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    {
+      if (it != arguments.begin())
+        output << ",";
+
+      (*it)->writeJsonOutput(output, output_type, temporary_terms, tef_terms);
+    }
+}
+
 void
 AbstractExternalFunctionNode::writePrhs(ostream &output, ExprNodeOutputType output_type,
                                         const temporary_terms_t &temporary_terms,
@@ -5054,6 +5358,16 @@ ExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsign
     }
 }
 
+void
+ExternalFunctionNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                                      const temporary_terms_t &temporary_terms,
+                                      deriv_node_temp_terms_t &tef_terms) const
+{
+  output << datatree.symbol_table.getName(symb_id) << "(";
+  writeJsonExternalFunctionArguments(output, output_type, temporary_terms, tef_terms);
+  output << ")";
+}
+
 void
 ExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
                                   const temporary_terms_t &temporary_terms,
@@ -5244,6 +5558,13 @@ FirstDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
   return theDeriv;
 }
 
+void
+FirstDerivExternalFunctionNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                                                const temporary_terms_t &temporary_terms,
+                                                deriv_node_temp_terms_t &tef_terms) const
+{
+}
+
 void
 FirstDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
                                             const temporary_terms_t &temporary_terms,
@@ -5556,6 +5877,13 @@ SecondDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
   exit(EXIT_FAILURE);
 }
 
+void
+SecondDerivExternalFunctionNode::writeJsonOutput(ostream &output, ExprNodeOutputType output_type,
+                                                 const temporary_terms_t &temporary_terms,
+                                                 deriv_node_temp_terms_t &tef_terms) const
+{
+}
+
 void
 SecondDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
                                              const temporary_terms_t &temporary_terms,
diff --git a/ExprNode.hh b/ExprNode.hh
index 0440d807f697aa60a9b0cd0ad0fe21428dc28b6e..326540719661b9496a8dec5e1383367584699702 100644
--- a/ExprNode.hh
+++ b/ExprNode.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2016 Dynare Team
+ * Copyright (C) 2007-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -221,6 +221,9 @@ public:
   //! Writes output of node, using a Txxx notation for nodes in temporary_terms
   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
 
+  //! Writes output of node in JSON syntax
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const = 0;
+
   //! Writes the output for an external function, ensuring that the external function is called as few times as possible using temporary terms
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
@@ -478,6 +481,7 @@ public:
   };
   virtual void prepareForDerivation();
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const;
   virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
@@ -527,6 +531,7 @@ public:
   VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg);
   virtual void prepareForDerivation();
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const;
   virtual void computeTemporaryTerms(map<expr_t, int > &reference_count,
@@ -602,6 +607,7 @@ public:
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
                                      bool is_matlab, NodeTreeReference tr) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
@@ -689,6 +695,7 @@ public:
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
                                      bool is_matlab, NodeTreeReference tr) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
@@ -794,6 +801,7 @@ public:
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
                                      bool is_matlab, NodeTreeReference tr) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
@@ -864,6 +872,7 @@ protected:
   int getIndxInTefTerms(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const throw (UnknownFunctionNameAndArgs);
   //! Helper function to write output arguments of any given external function
   void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  void writeJsonExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
 public:
   AbstractExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
                                const vector<expr_t> &arguments_arg);
@@ -872,6 +881,7 @@ public:
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
                                      bool is_matlab, NodeTreeReference tr) const = 0;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const = 0;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const = 0;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
@@ -938,6 +948,7 @@ public:
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
                                      bool is_matlab, NodeTreeReference tr) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
                                            deriv_node_temp_terms_t &tef_terms) const;
@@ -978,6 +989,7 @@ public:
                                      vector< vector<temporary_terms_t> > &v_temporary_terms,
                                      int equation) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
                        bool lhs_rhs, const temporary_terms_t &temporary_terms,
                        const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
@@ -1017,6 +1029,7 @@ public:
                                      vector< vector<temporary_terms_t> > &v_temporary_terms,
                                      int equation) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeJsonOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
                        bool lhs_rhs, const temporary_terms_t &temporary_terms,
                        const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
diff --git a/ExtendedPreprocessorTypes.hh b/ExtendedPreprocessorTypes.hh
index e0a955f2c8222b611512d31a296902b9e4e65fbd..1388cafc32910c22c1e76346abb95cc36725f97f 100644
--- a/ExtendedPreprocessorTypes.hh
+++ b/ExtendedPreprocessorTypes.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2015 Dynare Team
+ * Copyright (C) 2014-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -38,4 +38,10 @@ enum LanguageOutputType
     julia,                            // outputs files for Julia
     python,                           // outputs files for Python (not yet implemented) (not yet implemented)
   };
+
+enum JsonFileOutputType
+  {
+    file,                             // output JSON files to file
+    standardout,                      // output JSON files to stdout
+  };
 #endif
diff --git a/ModFile.cc b/ModFile.cc
index 794f1e46b1beca4b8dd904a544b822ae3ac93340..d269887380e3295ba95e4b281c2268ab13263a1a 100644
--- a/ModFile.cc
+++ b/ModFile.cc
@@ -1246,3 +1246,72 @@ ModFile::writeExternalFilesJulia(const string &basename, FileOutputType output)
   jlOutputFile.close();
   cout << "done" << endl;
 }
+
+void
+ModFile::writeJsonOutput(const string &basename, JsonFileOutputType json_output_mode) const
+{
+  ostringstream output;
+  output << "{" << endl;
+
+  symbol_table.writeJsonOutput(output);
+  dynamic_model.writeJsonOutput(output);
+
+  if (!statements.empty())
+    {
+      output << ",\"statements\": [";
+      bool printed_statement = false;
+      for (vector<Statement *>::const_iterator it = statements.begin();
+           it != statements.end();)
+        {
+          (*it)->writeJsonOutput(output);
+
+          if (dynamic_cast<InitParamStatement *>(*it) != NULL ||
+              dynamic_cast<InitValStatement *>(*it) != NULL ||
+              dynamic_cast<EndValStatement *>(*it) != NULL ||
+              dynamic_cast<HistValStatement *>(*it) != NULL)
+            printed_statement = true;
+
+          if (++it == statements.end())
+            break;
+
+          // tests to see if the next statement will be one for which we support writing JSON files
+          // to be deleted once we support all statements
+          if (printed_statement &&
+              (dynamic_cast<InitParamStatement *>(*it) != NULL ||
+               dynamic_cast<InitValStatement *>(*it) != NULL ||
+               dynamic_cast<EndValStatement *>(*it) != NULL ||
+               dynamic_cast<HistValStatement *>(*it) != NULL))
+            output << "," << endl;
+        }
+      output << "]" << endl;
+    }
+
+  output << "}" << endl;
+
+  if (json_output_mode == standardout)
+    cout << output.str();
+  else
+    {
+      ofstream jsonOutputFile;
+
+      if (basename.size())
+        {
+          string fname(basename);
+          fname += ".json";
+          jsonOutputFile.open(fname.c_str(), ios::out | ios::binary);
+          if (!jsonOutputFile.is_open())
+            {
+              cerr << "ERROR: Can't open file " << fname << " for writing" << endl;
+              exit(EXIT_FAILURE);
+            }
+        }
+       else
+         {
+           cerr << "ERROR: Missing file name" << endl;
+           exit(EXIT_FAILURE);
+         }
+
+      jsonOutputFile << output.str();
+      jsonOutputFile.close();
+    }
+}
diff --git a/ModFile.hh b/ModFile.hh
index 6ed24d33f767fa71c8c398c71935de040a6de4f7..b83f984da3f0d64e577f9a0a9473097f87d0b44d 100644
--- a/ModFile.hh
+++ b/ModFile.hh
@@ -167,6 +167,11 @@ public:
   void writeModelCC(const string &basename) const;
 
   void computeChecksum();
+  //! Write JSON representation of ModFile object
+  //! Initially created to enable Julia to work with .mod files
+  //! Potentially outputs ModFile after the various parts of processing (parsing, checkPass, transformPass, computingPass)
+  //! Allows user of other host language platforms (python, fortran, etc) to provide support for dynare .mod files
+  void writeJsonOutput(const string &basename, JsonFileOutputType json_output_mode) const;
 };
 
 #endif // ! MOD_FILE_HH
diff --git a/ModelTree.cc b/ModelTree.cc
index 70db28e01f05e404a6d20c577ecc0144d16b9a00..444aec2b390682acb7a50a61f98d6f64729504ad 100644
--- a/ModelTree.cc
+++ b/ModelTree.cc
@@ -1919,3 +1919,38 @@ bool ModelTree::isNonstationary(int symb_id) const
           != nonstationary_symbols_map.end());
 }
 
+void
+ModelTree::writeJsonModelEquations(ostream &output) const
+{
+  deriv_node_temp_terms_t tef_terms;
+  vector<pair<string,string> > eqtags;
+  output << endl << ",\"model\":[" << endl;
+  for (int eq = 0; eq < (int) equations.size(); eq++)
+    {
+      output << "{ \"equation\": \"";
+      equations[eq]->writeJsonOutput(output, oMatlabDynamicModel, temporary_terms, tef_terms);
+      output << "\", \"line\": " << equations_lineno[eq];
+      for (vector<pair<int, pair<string, string> > >::const_iterator it = equation_tags.begin();
+           it != equation_tags.end(); it++)
+        if (it->first == eq)
+          eqtags.push_back(it->second);
+
+      if (!eqtags.empty())
+        {
+          output << ", \"tags\": {";
+          int i = 0;
+          for (vector<pair<string, string> >:: const_iterator it = eqtags.begin(); it != eqtags.end(); it++, i++)
+            {
+              if (i != 0)
+                output << ", ";
+              output << "\"" << it->first << "\": \"" << it->second << "\"";
+            }
+          output << "}";
+          eqtags.clear();
+        }
+      output << "}";
+      if (eq < (int) equations.size() - 1)
+        output << "," << endl;
+    }
+  output << endl << "]" << endl;
+}
diff --git a/ModelTree.hh b/ModelTree.hh
index 9b28fce461a70060511cea90e0ec88a41b96fda9..d74598d89810d7e474a9d5fe6554f4819eec94a9 100644
--- a/ModelTree.hh
+++ b/ModelTree.hh
@@ -199,6 +199,8 @@ protected:
   void writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
   //! Writes model equations
   void writeModelEquations(ostream &output, ExprNodeOutputType output_type) const;
+  //! Writes JSON model equations
+  void writeJsonModelEquations(ostream &output) const;
   //! Compiles model equations
   void compileModelEquations(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic) const;
 
diff --git a/NumericalInitialization.cc b/NumericalInitialization.cc
index 3bbd803eba40724ca34dfa064b30a5aa9ba0a89e..6e4dcd263f02ed3ee7c2276b5dc4200e3adb23a0 100644
--- a/NumericalInitialization.cc
+++ b/NumericalInitialization.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2016 Dynare Team
+ * Copyright (C) 2003-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -63,6 +63,14 @@ InitParamStatement::writeJuliaOutput(ostream &output, const string &basename)
   //   output << symbol_table.getName(symb_id) << " = model_.params[ " << id << " ]" << endl;
 }
 
+void
+InitParamStatement::writeJsonOutput(ostream &output) const
+{
+  output << "{\"statementName\": \"param_init\", \"name\": \"" << symbol_table.getName(symb_id) << "\", " << "\"value\": ";
+  param_value->writeOutput(output);
+  output << "}";
+}
+
 void
 InitParamStatement::writeCOutput(ostream &output, const string &basename)
 {
@@ -165,6 +173,22 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
     }
 }
 
+void
+InitOrEndValStatement::writeJsonInitValues(ostream &output) const
+{
+  int i = 0;
+  deriv_node_temp_terms_t tef_terms;
+  for (init_values_t::const_iterator it = init_values.begin();
+       it != init_values.end(); it++, i++)
+    {
+      output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", " << "\"value\": \"";
+      it->second->writeJsonOutput(output, oMatlabOutsideModel, temporary_terms_t(), tef_terms);
+      output << "\"}";
+      if (i < init_values.size() - 1)
+        output << ", ";
+    }
+}
+
 InitValStatement::InitValStatement(const init_values_t &init_values_arg,
                                    const SymbolTable &symbol_table_arg,
                                    const bool &all_values_required_arg) :
@@ -210,6 +234,14 @@ InitValStatement::writeOutput(ostream &output, const string &basename, bool mini
   writeInitValues(output);
 }
 
+void
+InitValStatement::writeJsonOutput(ostream &output) const
+{
+  output << "{\"statementName\": \"init_val\", \"vals\": [";
+  writeJsonInitValues(output);
+  output << "]}";
+}
+
 void
 InitValStatement::writeOutputPostInit(ostream &output) const
 {
@@ -267,6 +299,14 @@ EndValStatement::writeOutput(ostream &output, const string &basename, bool minim
   writeInitValues(output);
 }
 
+void
+EndValStatement::writeJsonOutput(ostream &output) const
+{
+  output << "{\"statementName\": \"end_val\", \"vals\": [";
+  writeJsonInitValues(output);
+  output << "]}";
+}
+
 HistValStatement::HistValStatement(const hist_values_t &hist_values_arg,
                                    const SymbolTable &symbol_table_arg,
                                    const bool &all_values_required_arg) :
@@ -375,6 +415,26 @@ HistValStatement::writeOutput(ostream &output, const string &basename, bool mini
     }
 }
 
+void
+HistValStatement::writeJsonOutput(ostream &output) const
+{
+  int i = 0;
+  deriv_node_temp_terms_t tef_terms;
+  output << "{\"statementName\": \"hist_val\", \"vals\": [";
+  for (hist_values_t::const_iterator it = hist_values.begin();
+       it != hist_values.end(); it++)
+    {
+      output << "{ \"name\": \"" << symbol_table.getName(it->first.first) << "\""
+             << ", \"lag\": " << it->first.second
+             << ", \"value\": \"";
+      it->second->writeJsonOutput(output, oMatlabOutsideModel, temporary_terms_t(), tef_terms);
+      output << "\"}";
+      if (i < hist_values.size() - 1)
+        output << ", ";
+    }
+  output << "]}";
+}
+
 InitvalFileStatement::InitvalFileStatement(const string &filename_arg) :
   filename(filename_arg)
 {
diff --git a/NumericalInitialization.hh b/NumericalInitialization.hh
index 2e34677b816155039e4dce226f387938a9b84d0b..e48cb9ee796384dea3b4ab58e5912a904259121c 100644
--- a/NumericalInitialization.hh
+++ b/NumericalInitialization.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2016 Dynare Team
+ * Copyright (C) 2003-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -43,6 +43,7 @@ public:
   virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
   virtual void writeJuliaOutput(ostream &output, const string &basename);
   virtual void writeCOutput(ostream &output, const string &basename);
+  virtual void writeJsonOutput(ostream &output) const;
   //! Fill eval context with parameter value
   void fillEvalContext(eval_context_t &eval_context) const;
 };
@@ -69,6 +70,7 @@ public:
   void fillEvalContext(eval_context_t &eval_context) const;
 protected:
   void writeInitValues(ostream &output) const;
+  void writeJsonInitValues(ostream &output) const;
 };
 
 class InitValStatement : public InitOrEndValStatement
@@ -79,6 +81,7 @@ public:
                    const bool &all_values_required_arg);
   virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
   virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
+  virtual void writeJsonOutput(ostream &output) const;
   //! Writes initializations for oo_.exo_simul and oo_.exo_det_simul
   void writeOutputPostInit(ostream &output) const;
 };
@@ -92,6 +95,7 @@ public:
   //! Workaround for trac ticket #35
   virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
   virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
+  virtual void writeJsonOutput(ostream &output) const;
 };
 
 class HistValStatement : public Statement
@@ -114,6 +118,7 @@ public:
   //! Workaround for trac ticket #157
   virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
   virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
+  virtual void writeJsonOutput(ostream &output) const;
 };
 
 class InitvalFileStatement : public Statement
diff --git a/Statement.cc b/Statement.cc
index 887603b6d85f86d4059d5e6a6934d90a8779649e..ee18bbb835a88bbddd97c3422abb8076996bcef7 100644
--- a/Statement.cc
+++ b/Statement.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2015 Dynare Team
+ * Copyright (C) 2006-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -82,6 +82,10 @@ void Statement::writeJuliaOutput(ostream &output, const string &basename)
 {
 }
 
+void Statement::writeJsonOutput(ostream &output) const
+{
+}
+
 void
 Statement::computingPass()
 {
diff --git a/Statement.hh b/Statement.hh
index 311260b0e074e09578c4378a92d9f9a0b4d5f4b5..0db8a3c8c6dbb0761d310e548299bbd2df528fe4 100644
--- a/Statement.hh
+++ b/Statement.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2015 Dynare Team
+ * Copyright (C) 2006-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -144,6 +144,7 @@ public:
   virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const = 0;
   virtual void writeCOutput(ostream &output, const string &basename);
   virtual void writeJuliaOutput(ostream &output, const string &basename);
+  virtual void writeJsonOutput(ostream &output) const;
 };
 
 class NativeStatement : public Statement
diff --git a/SymbolTable.cc b/SymbolTable.cc
index 17b63e953136a1fd482a0ebaf361d724abedc2cb..84deb2a5ff61df0e3fc686cbadeaaffa83ceec9b 100644
--- a/SymbolTable.cc
+++ b/SymbolTable.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2016 Dynare Team
+ * Copyright (C) 2003-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -21,6 +21,7 @@
 #include <sstream>
 #include <iostream>
 #include <cassert>
+#include <boost/algorithm/string/replace.hpp>
 
 #include "SymbolTable.hh"
 
@@ -138,6 +139,17 @@ SymbolTable::freeze() throw (FrozenException)
     }
 }
 
+void
+SymbolTable::unfreeze()
+{
+  frozen = false;
+  endo_ids.clear();
+  exo_ids.clear();
+  exo_det_ids.clear();
+  param_ids.clear();
+  type_specific_ids.clear();
+}
+
 void
 SymbolTable::changeType(int id, SymbolType newtype) throw (UnknownSymbolIDException, FrozenException)
 {
@@ -950,3 +962,74 @@ SymbolTable::writeJuliaOutput(ostream &output) const throw (NotYetFrozenExceptio
         output << "                   ]" << endl;
       }
 }
+
+void
+SymbolTable::writeJsonOutput(ostream &output) const
+{/*
+  vector<int> endos, exos, exo_dets, params;
+  for (int i = 0; i < size; i++)
+    {
+      switch (getType(i))
+        {
+        case eEndogenous:
+          endos.push_back(i);
+          break;
+        case eExogenous:
+          exos.push_back(i);
+          break;
+        case eExogenousDet:
+          exo_dets.push_back(i);
+          break;
+        case eParameter:
+          params.push_back(i);
+          break;
+        default:
+          break;
+        }
+    }
+ */
+
+  if (!endo_ids.empty())
+    {
+      output << "\"endogenous\":";
+      writeJsonVarVector(output, endo_ids);
+      output << endl;
+    }
+
+  if (!exo_ids.empty())
+    {
+      output << ",\"exogenous\":";
+      writeJsonVarVector(output, exo_ids);
+      output << endl;
+    }
+
+  if (!exo_det_ids.empty())
+    {
+      output << ",\"exogenous_deterministic\":";
+      writeJsonVarVector(output, exo_det_ids);
+      output << endl;
+    }
+
+  if (!param_ids.empty())
+    {
+      output << ",\"parameters\":";
+      writeJsonVarVector(output, param_ids);
+      cout << endl;
+    }
+}
+
+void
+SymbolTable::writeJsonVarVector(ostream &output, const vector<int> &varvec) const
+{
+  output << "[";
+  for (int i = 0; i < varvec.size(); i++)
+    {
+      output << endl << "{"
+             << "\"name\":\" " << getName(varvec[i]) << "\", "
+             << "\"texName\":\" " << boost::replace_all_copy(getTeXName(varvec[i]), "\\", "\\\\") << "\", "
+             << "\"longName\":\" " << boost::replace_all_copy(getLongName(varvec[i]), "\\", "\\\\") << "\"}";
+      if (i < varvec.size() - 1)
+        output << ", ";
+    }
+  output << endl << "]";
+}
diff --git a/SymbolTable.hh b/SymbolTable.hh
index c99dd462ffac9be892a67e9209e2624644e6fb05..370c5e774bc1cbd77f95d612aa2a419a00397af2 100644
--- a/SymbolTable.hh
+++ b/SymbolTable.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2016 Dynare Team
+ * Copyright (C) 2003-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -192,7 +192,8 @@ private:
   int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t arg) throw (FrozenException);
   //! Factorized code for adding aux lead variables
   int addLeadAuxiliaryVarInternal(bool endo, int index, expr_t arg) throw (FrozenException);
-
+  //! Factorized code for Json writing
+  void writeJsonVarVector(ostream &output, const vector<int> &varvec) const;
 public:
   //! Add a symbol
   /*! Returns the symbol ID */
@@ -274,6 +275,9 @@ public:
   int getID(SymbolType type, int tsid) const throw (UnknownTypeSpecificIDException, NotYetFrozenException);
   //! Freeze symbol table
   void freeze() throw (FrozenException);
+  //! unreeze symbol table
+  //! Used after having written JSON files
+  void unfreeze();
   //! Change the type of a symbol
   void changeType(int id, SymbolType newtype) throw (UnknownSymbolIDException, FrozenException);
   //! Get type specific ID (by symbol ID)
@@ -294,6 +298,8 @@ public:
   inline int orig_endo_nbr() const throw (NotYetFrozenException);
   //! Write output of this class
   void writeOutput(ostream &output) const throw (NotYetFrozenException);
+  //! Write JSON Output
+  void writeJsonOutput(ostream &output) const;
   //! Write Julia output of this class
   void writeJuliaOutput(ostream &output) const throw (NotYetFrozenException);
   //! Write C output of this class